1663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
2663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/*---------------------------------------------------------------*/
3436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov/*--- begin                                  host_mips_isel.c ---*/
4663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/*---------------------------------------------------------------*/
5663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
6663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/*
7663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   This file is part of Valgrind, a dynamic binary instrumentation
8663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   framework.
9663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
10436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   Copyright (C) 2010-2013 RT-RK
11663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      mips-valgrind@rt-rk.com
12663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
13663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   This program is free software; you can redistribute it and/or
14663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   modify it under the terms of the GNU General Public License as
15663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   published by the Free Software Foundation; either version 2 of the
16663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   License, or (at your option) any later version.
17663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
18663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   This program is distributed in the hope that it will be useful, but
19663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   WITHOUT ANY WARRANTY; without even the implied warranty of
20663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
21663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   General Public License for more details.
22663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
23663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   You should have received a copy of the GNU General Public License
24663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   along with this program; if not, write to the Free Software
25663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
26663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   02110-1301, USA.
27663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
28663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   The GNU General Public License is contained in the file COPYING.
29663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng*/
30663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
31663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#include "libvex_basictypes.h"
32663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#include "libvex_ir.h"
33663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#include "libvex.h"
34663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
35663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#include "main_util.h"
36663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#include "main_globals.h"
37663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#include "host_generic_regs.h"
38436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#include "host_generic_simd64.h"  /* for 64-bit SIMD helpers */
39663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#include "host_mips_defs.h"
40663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
41663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/*---------------------------------------------------------*/
42663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/*--- Register Usage Conventions                        ---*/
43663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/*---------------------------------------------------------*/
44663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
45436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov/* Integer Regs
46436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   ------------
47436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   ZERO0       Reserved
48436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   GPR12:22    Allocateable
49436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   23          GuestStatePointer
50436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   SP          StackFramePointer
51436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   RA          LinkRegister */
52663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
53663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic Bool mode64 = False;
54663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
55436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov/* Host CPU has FPU and 32 dbl. prec. FP registers. */
56436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstatic Bool fp_mode64 = False;
57436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
58663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* GPR register class for mips32/64 */
59663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#define HRcGPR(__mode64) (__mode64 ? HRcInt64 : HRcInt32)
60663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
61663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* FPR register class for mips32/64 */
62663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#define HRcFPR(__mode64) (__mode64 ? HRcFlt64 : HRcFlt32)
63663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
64436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov/* guest_COND offset */
65436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#define COND_OFFSET(__mode64) (__mode64 ? 612 : 448)
66436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
67663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/*---------------------------------------------------------*/
68663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/*--- ISelEnv                                           ---*/
69663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/*---------------------------------------------------------*/
70663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
71663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* This carries around:
72663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
73663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   - A mapping from IRTemp to IRType, giving the type of any IRTemp we
74663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng     might encounter.  This is computed before insn selection starts,
75663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng     and does not change.
76663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
77663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   - A mapping from IRTemp to HReg.  This tells the insn selector
78663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng     which virtual register(s) are associated with each IRTemp
79663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng     temporary.  This is computed before insn selection starts, and
80663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng     does not change.  We expect this mapping to map precisely the
81663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng     same set of IRTemps as the type mapping does.
82663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
83663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        - vregmap   holds the primary register for the IRTemp.
84663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        - vregmapHI is only used for 64-bit integer-typed
85663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng             IRTemps.  It holds the identity of a second
86663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng             32-bit virtual HReg, which holds the high half
87663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng             of the value.
88663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
89663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   - The code array, that is, the insns selected so far.
90663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
91663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   - A counter, for generating new virtual registers.
92663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
93436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   - The host subarchitecture we are selecting insns for.
94663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng     This is set at the start and does not change.
95663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
96663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   - A Bool for indicating whether we may generate chain-me
97663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng     instructions for control flow transfers, or whether we must use
98663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng     XAssisted.
99663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
100663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   - The maximum guest address of any guest insn in this block.
101663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng     Actually, the address of the highest-addressed byte from any insn
102663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng     in this block.  Is set at the start and does not change.  This is
103663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng     used for detecting jumps which are definitely forward-edges from
104663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng     this block, and therefore can be made (chained) to the fast entry
105663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng     point of the destination, thereby avoiding the destination's
106663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng     event check.
107663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
108663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   Note, this is all (well, mostly) host-independent.
109663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng*/
110663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
111663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengtypedef
112663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   struct {
113663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* Constant -- are set at the start and do not change. */
114663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      IRTypeEnv*   type_env;
115663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
116663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      HReg*        vregmap;
117663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      HReg*        vregmapHI;
118663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      Int          n_vregmap;
119663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
120663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      UInt         hwcaps;
121663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      Bool         mode64;
122436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      Bool         fp_mode64;
123663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
124663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      Bool         chainingAllowed;
125663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      Addr64       max_ga;
126663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
127663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* These are modified as we go along. */
128663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      HInstrArray* code;
129663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      Int          vreg_ctr;
130663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
131663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   ISelEnv;
132663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
133663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic HReg lookupIRTemp(ISelEnv * env, IRTemp tmp)
134663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
135663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vassert(tmp >= 0);
136663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vassert(tmp < env->n_vregmap);
137663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return env->vregmap[tmp];
138663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
139663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
140663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic void lookupIRTemp64(HReg * vrHI, HReg * vrLO, ISelEnv * env, IRTemp tmp)
141663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
142663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vassert(tmp >= 0);
143663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vassert(tmp < env->n_vregmap);
144436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   vassert(! hregIsInvalid(env->vregmapHI[tmp]));
145663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   *vrLO = env->vregmap[tmp];
146663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   *vrHI = env->vregmapHI[tmp];
147663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
148663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
149663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic void
150663860b1408516d02ebfcb3a9999a134e6cfb223Ben ChenglookupIRTempPair(HReg * vrHI, HReg * vrLO, ISelEnv * env, IRTemp tmp)
151663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
152663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vassert(env->mode64);
153663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vassert(tmp >= 0);
154663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vassert(tmp < env->n_vregmap);
155436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   vassert(! hregIsInvalid(env->vregmapHI[tmp]));
156663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   *vrLO = env->vregmap[tmp];
157663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   *vrHI = env->vregmapHI[tmp];
158663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
159663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
160663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic void addInstr(ISelEnv * env, MIPSInstr * instr)
161663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
162663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   addHInstr(env->code, instr);
163663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (vex_traceflags & VEX_TRACE_VCODE) {
164663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      ppMIPSInstr(instr, mode64);
165663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      vex_printf("\n");
166663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
167663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
168663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
169663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic HReg newVRegI(ISelEnv * env)
170663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
171436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   HReg reg = mkHReg(env->vreg_ctr, HRcGPR(env->mode64),
172663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                     True /*virtual reg */ );
173663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   env->vreg_ctr++;
174663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return reg;
175663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
176663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
177663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic HReg newVRegD(ISelEnv * env)
178663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
179663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   HReg reg = mkHReg(env->vreg_ctr, HRcFlt64, True /*virtual reg */ );
180663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   env->vreg_ctr++;
181663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return reg;
182663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
183663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
184663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic HReg newVRegF(ISelEnv * env)
185663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
186436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   HReg reg = mkHReg(env->vreg_ctr, HRcFPR(env->fp_mode64),
187663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                     True /*virtual reg */ );
188663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   env->vreg_ctr++;
189663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return reg;
190663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
191663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
192663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic void add_to_sp(ISelEnv * env, UInt n)
193663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
194663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   HReg sp = StackPointer(mode64);
195663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vassert(n < 256 && (n % 8) == 0);
196436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   if (mode64)
197436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      addInstr(env, MIPSInstr_Alu(Malu_DADD, sp, sp, MIPSRH_Imm(True,
198436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                                                toUShort(n))));
199436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   else
200436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      addInstr(env, MIPSInstr_Alu(Malu_ADD, sp, sp, MIPSRH_Imm(True,
201436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                                               toUShort(n))));
202663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
203663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
204663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic void sub_from_sp(ISelEnv * env, UInt n)
205663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
206663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   HReg sp = StackPointer(mode64);
207663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vassert(n < 256 && (n % 8) == 0);
208436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   if (mode64)
209436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      addInstr(env, MIPSInstr_Alu(Malu_DSUB, sp, sp,
210436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                  MIPSRH_Imm(True, toUShort(n))));
211436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   else
212436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      addInstr(env, MIPSInstr_Alu(Malu_SUB, sp, sp,
213436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                  MIPSRH_Imm(True, toUShort(n))));
214663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
215663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
216663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/*---------------------------------------------------------*/
217663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/*--- ISEL: Forward declarations                        ---*/
218663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/*---------------------------------------------------------*/
219663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
220663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* These are organised as iselXXX and iselXXX_wrk pairs.  The
221663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   iselXXX_wrk do the real work, but are not to be called directly.
222663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   For each XXX, iselXXX calls its iselXXX_wrk counterpart, then
223663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   checks that all returned registers are virtual.  You should not
224663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   call the _wrk version directly.
225663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng*/
226663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* 32-bit mode: Compute an I8/I16/I32 into a RH
227663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                (reg-or-halfword-immediate).
228663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   It's important to specify whether the immediate is to be regarded
229663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   as signed or not.  If yes, this will never return -32768 as an
230663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   immediate; this guaranteed that all signed immediates that are
231436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   return can have their sign inverted if need be.
232663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng*/
233663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic MIPSRH *iselWordExpr_RH_wrk(ISelEnv * env, Bool syned, IRExpr * e);
234663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic MIPSRH *iselWordExpr_RH(ISelEnv * env, Bool syned, IRExpr * e);
235663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
236436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov/* Compute an I8 into a reg-or-5-bit-unsigned-immediate, the latter being an
237436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   immediate in the range 1 .. 31 inclusive.  Used for doing shift amounts. */
238663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic MIPSRH *iselWordExpr_RH5u_wrk(ISelEnv * env, IRExpr * e);
239663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic MIPSRH *iselWordExpr_RH5u(ISelEnv * env, IRExpr * e);
240663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
241436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov/* Compute an I8 into a reg-or-6-bit-unsigned-immediate, the latter being an
242436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   immediate in the range 1 .. 63 inclusive.  Used for doing shift amounts. */
243436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstatic MIPSRH *iselWordExpr_RH6u_wrk(ISelEnv * env, IRExpr * e);
244436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstatic MIPSRH *iselWordExpr_RH6u(ISelEnv * env, IRExpr * e);
245436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
246663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* compute an I8/I16/I32 into a GPR*/
247663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic HReg iselWordExpr_R_wrk(ISelEnv * env, IRExpr * e);
248663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic HReg iselWordExpr_R(ISelEnv * env, IRExpr * e);
249663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
250663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* compute an I32 into an AMode. */
251663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic MIPSAMode *iselWordExpr_AMode_wrk(ISelEnv * env, IRExpr * e,
252663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                         IRType xferTy);
253663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic MIPSAMode *iselWordExpr_AMode(ISelEnv * env, IRExpr * e, IRType xferTy);
254663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
255663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic void iselInt64Expr_wrk(HReg * rHi, HReg * rLo, ISelEnv * env,
256663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                              IRExpr * e);
257663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic void iselInt64Expr(HReg * rHi, HReg * rLo, ISelEnv * env, IRExpr * e);
258663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
259663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* 64-bit mode ONLY: compute an I128 into a GPR64 pair. */
260663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic void iselInt128Expr_wrk(HReg * rHi, HReg * rLo,
261663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                               ISelEnv * env, IRExpr * e);
262663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic void iselInt128Expr(HReg * rHi, HReg * rLo, ISelEnv * env, IRExpr * e);
263663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
264663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic MIPSCondCode iselCondCode_wrk(ISelEnv * env, IRExpr * e);
265663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic MIPSCondCode iselCondCode(ISelEnv * env, IRExpr * e);
266663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
267663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic HReg iselDblExpr_wrk(ISelEnv * env, IRExpr * e);
268663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic HReg iselDblExpr(ISelEnv * env, IRExpr * e);
269663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
270663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic HReg iselFltExpr_wrk(ISelEnv * env, IRExpr * e);
271663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic HReg iselFltExpr(ISelEnv * env, IRExpr * e);
272663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
273663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic void set_MIPS_rounding_mode(ISelEnv * env, IRExpr * mode)
274663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
275663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /*
276663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      rounding mode | MIPS | IR
277663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      ------------------------
278663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      to nearest    | 00  | 00
279663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      to zero       | 01  | 11
280663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      to +infinity  | 10  | 10
281663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      to -infinity  | 11  | 01
282663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng    */
283436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   /* rm_MIPS32  = XOR(rm_IR , (rm_IR << 1)) & 2 */
284663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   HReg irrm = iselWordExpr_R(env, mode);
285663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   HReg tmp = newVRegI(env);
286663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   HReg fcsr_old = newVRegI(env);
287663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   MIPSAMode *am_addr;
288663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
289663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   addInstr(env, MIPSInstr_Shft(Mshft_SLL, True, tmp, irrm,
290663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                MIPSRH_Imm(False, 1)));
291663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   addInstr(env, MIPSInstr_Alu(Malu_XOR, tmp, irrm, MIPSRH_Reg(tmp)));
292663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   addInstr(env, MIPSInstr_Alu(Malu_AND, irrm, tmp, MIPSRH_Imm(False, 3)));
293663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* save old value of FCSR */
294663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   addInstr(env, MIPSInstr_MfFCSR(fcsr_old));
295436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   sub_from_sp(env, 8); /*  Move SP down 8 bytes */
296663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   am_addr = MIPSAMode_IR(0, StackPointer(mode64));
297663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
298436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   /* store old FCSR to stack */
299663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   addInstr(env, MIPSInstr_Store(4, am_addr, fcsr_old, mode64));
300663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
301436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   /* set new value of FCSR */
302663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   addInstr(env, MIPSInstr_MtFCSR(irrm));
303663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
304663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
305663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic void set_MIPS_rounding_default(ISelEnv * env)
306663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
307663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   HReg fcsr = newVRegI(env);
308436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   /* load as float */
309663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   MIPSAMode *am_addr;
310663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   am_addr = MIPSAMode_IR(0, StackPointer(mode64));
311663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
312663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   addInstr(env, MIPSInstr_Load(4, fcsr, am_addr, mode64));
313663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
314436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   add_to_sp(env, 8);  /* Reset SP */
315663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
316436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   /* set new value of FCSR*/
317663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   addInstr(env, MIPSInstr_MtFCSR(fcsr));
318663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
319663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
320663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/*---------------------------------------------------------*/
321663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/*--- ISEL: Misc helpers                                ---*/
322663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/*---------------------------------------------------------*/
323663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
324663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* Make an int reg-reg move. */
325663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic MIPSInstr *mk_iMOVds_RR(HReg r_dst, HReg r_src)
326663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
327663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vassert(hregClass(r_dst) == hregClass(r_src));
328663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vassert(hregClass(r_src) == HRcInt32 || hregClass(r_src) == HRcInt64);
329663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return MIPSInstr_Alu(Malu_OR, r_dst, r_src, MIPSRH_Reg(r_src));
330663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
331663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
332663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/*---------------------------------------------------------*/
333663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/*--- ISEL: Function call helpers                       ---*/
334663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/*---------------------------------------------------------*/
335663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
336663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* Used only in doHelperCall.  See big comment in doHelperCall re
337663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   handling of register-parameter args.  This function figures out
338663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   whether evaluation of an expression might require use of a fixed
339663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   register.  If in doubt return True (safe but suboptimal).
340663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng*/
341663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic Bool mightRequireFixedRegs(IRExpr * e)
342663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
343663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   switch (e->tag) {
344663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Iex_RdTmp:
345663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Iex_Const:
346663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Iex_Get:
347663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         return False;
348663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      default:
349663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         return True;
350663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
351663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
352663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
353663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* Load 2*I32 regs to fp reg */
354663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic HReg mk_LoadRR32toFPR(ISelEnv * env, HReg r_srcHi, HReg r_srcLo)
355663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
356663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   HReg fr_dst = newVRegD(env);
357663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   MIPSAMode *am_addr0, *am_addr1;
358663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
359663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vassert(hregClass(r_srcHi) == HRcInt32);
360663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vassert(hregClass(r_srcLo) == HRcInt32);
361663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
362436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   sub_from_sp(env, 16);  /* Move SP down 16 bytes */
363663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   am_addr0 = MIPSAMode_IR(0, StackPointer(mode64));
364436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   am_addr1 = MIPSAMode_IR(4, StackPointer(mode64));
365663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
366436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   /* store hi,lo as Ity_I32's */
367436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#if defined (_MIPSEL)
368663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   addInstr(env, MIPSInstr_Store(4, am_addr0, r_srcLo, mode64));
369663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   addInstr(env, MIPSInstr_Store(4, am_addr1, r_srcHi, mode64));
370436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#elif defined (_MIPSEB)
371436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   addInstr(env, MIPSInstr_Store(4, am_addr0, r_srcHi, mode64));
372436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   addInstr(env, MIPSInstr_Store(4, am_addr1, r_srcLo, mode64));
373436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#else
374436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   /* Stop gcc on other platforms complaining about am_addr1 being set
375436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      but not used. */
376436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   (void)am_addr1;
377436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#endif
378436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
379436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   /* load as float */
380663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   addInstr(env, MIPSInstr_FpLdSt(True /*load */ , 8, fr_dst, am_addr0));
381663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
382436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   add_to_sp(env, 16);  /* Reset SP */
383663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return fr_dst;
384663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
385663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
386436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov/* Do a complete function call.  |guard| is a Ity_Bit expression
387663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   indicating whether or not the call happens.  If guard==NULL, the
388436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   call is unconditional.  |retloc| is set to indicate where the
389436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   return value is after the call.  The caller (of this fn) must
390436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   generate code to add |stackAdjustAfterCall| to the stack pointer
391436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   after the call is done. */
392436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
393436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstatic void doHelperCall(/*OUT*/UInt*   stackAdjustAfterCall,
394436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                         /*OUT*/RetLoc* retloc,
395436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                         ISelEnv* env,
396436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                         IRExpr* guard,
397436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                         IRCallee* cee, IRType retTy, IRExpr** args )
398663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
399663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   MIPSCondCode cc;
400663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   HReg argregs[MIPS_N_REGPARMS];
401663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   HReg tmpregs[MIPS_N_REGPARMS];
402663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   Bool go_fast;
403663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   Int n_args, i, argreg;
404663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UInt argiregs;
405436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   HReg src = INVALID_HREG;
406436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
407436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   /* Set default returns.  We'll update them later if needed. */
408436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   *stackAdjustAfterCall = 0;
409436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   *retloc               = mk_RetLoc_INVALID();
410436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
411436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   /* These are used for cross-checking that IR-level constraints on
412436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      the use of IRExpr_VECRET() and IRExpr_BBPTR() are observed. */
413436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   UInt nVECRETs = 0;
414436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   UInt nBBPTRs  = 0;
415663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
416663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* MIPS O32 calling convention: up to four registers ($a0 ... $a3)
417663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      are allowed to be used for passing integer arguments. They correspond
418436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      to regs GPR4 ... GPR7. Note that the cee->regparms field is meaningless
419436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      on MIPS host (since we only implement one calling convention) and so we
420663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      always ignore it. */
421663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
422663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* MIPS 64 calling convention: up to four registers ($a0 ... $a7)
423663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      are allowed to be used for passing integer arguments. They correspond
424436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      to regs GPR4 ... GPR11. Note that the cee->regparms field is meaningless
425436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      on MIPS host (since we only implement one calling convention) and so we
426663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      always ignore it. */
427436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
428436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   /* The return type can be I{64,32,16,8} or V{128,256}.  In the
429436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      latter two cases, it is expected that |args| will contain the
430436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      special node IRExpr_VECRET(), in which case this routine
431436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      generates code to allocate space on the stack for the vector
432436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      return value.  Since we are not passing any scalars on the
433436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      stack, it is enough to preallocate the return space before
434436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      marshalling any arguments, in this case.
435436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
436436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      |args| may also contain IRExpr_BBPTR(), in which case the value
437436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      in the guest state pointer register is passed as the
438436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      corresponding argument. */
439436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
440663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   n_args = 0;
441436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   for (i = 0; args[i]; i++) {
442436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      IRExpr* arg = args[i];
443436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      if (UNLIKELY(arg->tag == Iex_VECRET)) {
444436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         nVECRETs++;
445436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      } else if (UNLIKELY(arg->tag == Iex_BBPTR)) {
446436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         nBBPTRs++;
447436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      }
448663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      n_args++;
449663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
450663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
451436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   if (n_args > MIPS_N_REGPARMS) {
452436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      vpanic("doHelperCall(MIPS): cannot currently handle > 4 or 8 args");
453436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   }
454436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   if (mode64) {
455436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      argregs[0] = hregMIPS_GPR4(mode64);
456436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      argregs[1] = hregMIPS_GPR5(mode64);
457436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      argregs[2] = hregMIPS_GPR6(mode64);
458436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      argregs[3] = hregMIPS_GPR7(mode64);
459436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      argregs[4] = hregMIPS_GPR8(mode64);
460436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      argregs[5] = hregMIPS_GPR9(mode64);
461436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      argregs[6] = hregMIPS_GPR10(mode64);
462436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      argregs[7] = hregMIPS_GPR11(mode64);
463436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      argiregs = 0;
464436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      tmpregs[0] = tmpregs[1] = tmpregs[2] =
465436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      tmpregs[3] = tmpregs[4] = tmpregs[5] =
466436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      tmpregs[6] = tmpregs[7] = INVALID_HREG;
467436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   } else {
468436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      argregs[0] = hregMIPS_GPR4(mode64);
469436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      argregs[1] = hregMIPS_GPR5(mode64);
470436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      argregs[2] = hregMIPS_GPR6(mode64);
471436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      argregs[3] = hregMIPS_GPR7(mode64);
472436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      argiregs = 0;
473436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      tmpregs[0] = tmpregs[1] = tmpregs[2] = tmpregs[3] = INVALID_HREG;
474436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   }
475663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
476436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   /* First decide which scheme (slow or fast) is to be used. First assume the
477436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      fast scheme, and select slow if any contraindications (wow) appear. */
478663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
479663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   go_fast = True;
480663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
481436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   /* We'll need space on the stack for the return value.  Avoid
482436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      possible complications with nested calls by using the slow
483436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      scheme. */
484436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   if (retTy == Ity_V128 || retTy == Ity_V256)
485436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      go_fast = False;
486436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
487436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   if (go_fast && guard) {
488663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (guard->tag == Iex_Const && guard->Iex.Const.con->tag == Ico_U1
489663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          && guard->Iex.Const.con->Ico.U1 == True) {
490663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* unconditional */
491663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      } else {
492663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* Not manifestly unconditional -- be conservative. */
493663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         go_fast = False;
494663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
495663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
496663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
497663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (go_fast) {
498663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      for (i = 0; i < n_args; i++) {
499663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (mightRequireFixedRegs(args[i])) {
500663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            go_fast = False;
501663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            break;
502663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
503663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
504663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
505663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
506663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* At this point the scheme to use has been established.  Generate
507663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      code to get the arg values into the argument rregs. */
508663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (go_fast) {
509663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* FAST SCHEME */
510663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      argreg = 0;
511663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
512663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      for (i = 0; i < n_args; i++) {
513436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         IRExpr* arg = args[i];
514663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         vassert(argreg < MIPS_N_REGPARMS);
515436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
516436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         IRType  aTy = Ity_INVALID;
517436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         if (LIKELY(!is_IRExpr_VECRET_or_BBPTR(arg)))
518436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            aTy = typeOfIRExpr(env->type_env, arg);
519436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
520436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         if (aTy == Ity_I32 || mode64) {
521663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            argiregs |= (1 << (argreg + 4));
522436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            addInstr(env, mk_iMOVds_RR(argregs[argreg],
523436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                       iselWordExpr_R(env, arg)));
524436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            argreg++;
525436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         } else if (aTy == Ity_I64) {  /* Ity_I64 */
526436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            if (argreg & 1) {
527436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               argreg++;
528436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               argiregs |= (1 << (argreg + 4));
529436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            }
530436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            HReg rHi, rLo;
531436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            iselInt64Expr(&rHi, &rLo, env, arg);
532663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            argiregs |= (1 << (argreg + 4));
533436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            addInstr(env, mk_iMOVds_RR( argregs[argreg++], rHi ));
534436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            argiregs |= (1 << (argreg + 4));
535436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            addInstr(env, mk_iMOVds_RR( argregs[argreg], rLo));
536436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            argreg++;
537436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         } else if (arg->tag == Iex_BBPTR) {
538436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            vassert(0);  // ATC
539436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            addInstr(env, mk_iMOVds_RR(argregs[argreg],
540436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                       GuestStatePointer(mode64)));
541436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            argreg++;
542436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         } else if (arg->tag == Iex_VECRET) {
543436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            // If this happens, it denotes ill-formed IR.
544436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            vassert(0);
545663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
546663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
547663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* Fast scheme only applies for unconditional calls.  Hence: */
548663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      cc = MIPScc_AL;
549663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   } else {
550663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* SLOW SCHEME; move via temporaries */
551663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      argreg = 0;
552436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
553663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      for (i = 0; i < n_args; i++) {
554663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         vassert(argreg < MIPS_N_REGPARMS);
555436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         IRExpr* arg = args[i];
556436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
557436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         IRType  aTy = Ity_INVALID;
558436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         if (LIKELY(!is_IRExpr_VECRET_or_BBPTR(arg)))
559436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            aTy  = typeOfIRExpr(env->type_env, arg);
560436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
561436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         if (aTy == Ity_I32 || (mode64 && arg->tag != Iex_BBPTR)) {
562436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            tmpregs[argreg] = iselWordExpr_R(env, arg);
563436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            argreg++;
564436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         } else if (aTy == Ity_I64) {  /* Ity_I64 */
565436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            if (argreg & 1)
566436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               argreg++;
567436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            if (argreg + 1 >= MIPS_N_REGPARMS)
568436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               vassert(0);  /* out of argregs */
569436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            HReg raHi, raLo;
570436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            iselInt64Expr(&raHi, &raLo, env, arg);
571436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            tmpregs[argreg] = raLo;
572436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            argreg++;
573436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            tmpregs[argreg] = raHi;
574436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            argreg++;
575436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         } else if (arg->tag == Iex_BBPTR) {
576436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            tmpregs[argreg] = GuestStatePointer(mode64);
577436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            argreg++;
578436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         }
579436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         else if (arg->tag == Iex_VECRET) {
580436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            // If this happens, it denotes ill-formed IR
581436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            vassert(0);
582663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
583663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
584663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
585663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* Now we can compute the condition.  We can't do it earlier
586663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         because the argument computations could trash the condition
587663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         codes.  Be a bit clever to handle the common case where the
588663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         guard is 1:Bit. */
589663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      cc = MIPScc_AL;
590663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (guard) {
591663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (guard->tag == Iex_Const && guard->Iex.Const.con->tag == Ico_U1
592663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng             && guard->Iex.Const.con->Ico.U1 == True) {
593663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            /* unconditional -- do nothing */
594663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         } else {
595663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            cc = iselCondCode(env, guard);
596663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            src = iselWordExpr_R(env, guard);
597663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
598663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
599663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* Move the args to their final destinations. */
600663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      for (i = 0; i < argreg; i++) {
601436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         if (hregIsInvalid(tmpregs[i]))  /* Skip invalid regs */
602663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            continue;
603663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* None of these insns, including any spill code that might
604663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            be generated, may alter the condition codes. */
605663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         argiregs |= (1 << (i + 4));
606663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         addInstr(env, mk_iMOVds_RR(argregs[i], tmpregs[i]));
607663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
608663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
609663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
610436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   /* Do final checks, set the return values, and generate the call
611436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      instruction proper. */
612436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   vassert(nBBPTRs == 0 || nBBPTRs == 1);
613436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   vassert(nVECRETs == (retTy == Ity_V128 || retTy == Ity_V256) ? 1 : 0);
614436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   vassert(*stackAdjustAfterCall == 0);
615436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   vassert(is_RetLoc_INVALID(*retloc));
616436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   switch (retTy) {
617436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Ity_INVALID:
618436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         /* Function doesn't return a value. */
619436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         *retloc = mk_RetLoc_simple(RLPri_None);
620436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         break;
621436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Ity_I64:
622436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         *retloc = mk_RetLoc_simple(mode64 ? RLPri_Int : RLPri_2Int);
623436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         break;
624436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Ity_I32: case Ity_I16: case Ity_I8:
625436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         *retloc = mk_RetLoc_simple(RLPri_Int);
626436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         break;
627436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Ity_V128:
628436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         vassert(0); // ATC
629436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         *retloc = mk_RetLoc_spRel(RLPri_V128SpRel, 0);
630436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         *stackAdjustAfterCall = 16;
631436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         break;
632436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Ity_V256:
633436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         vassert(0); // ATC
634436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         *retloc = mk_RetLoc_spRel(RLPri_V256SpRel, 0);
635436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         *stackAdjustAfterCall = 32;
636436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         break;
637436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      default:
638436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         /* IR can denote other possible return types, but we don't
639436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            handle those here. */
640436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov        vassert(0);
641663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
642436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
643436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   ULong target = mode64 ? Ptr_to_ULong(cee->addr) :
644436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                           toUInt(Ptr_to_ULong(cee->addr));
645436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
646436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   /* Finally, generate the call itself.  This needs the *retloc value
647436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      set in the switch above, which is why it's at the end. */
648436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   if (cc == MIPScc_AL)
649436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      addInstr(env, MIPSInstr_CallAlways(cc, (Addr64)target, argiregs,
650436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                         *retloc));
651436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   else
652436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      addInstr(env, MIPSInstr_Call(cc, (Addr64)target, argiregs, src, *retloc));
653663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
654663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
655663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/*---------------------------------------------------------*/
656663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/*--- ISEL: Integer expression auxiliaries              ---*/
657663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/*---------------------------------------------------------*/
658663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
659663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* --------------------- AMODEs --------------------- */
660663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
661663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* Return an AMode which computes the value of the specified
662663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   expression, possibly also adding insns to the code list as a
663663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   result.  The expression may only be a word-size one.
664663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng*/
665663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
666663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic Bool uInt_fits_in_16_bits(UInt u)
667663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
668663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   Int i = u & 0xFFFF;
669663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   i <<= 16;
670663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   i >>= 16;
671663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return toBool(u == (UInt) i);
672663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
673663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
674436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstatic Bool uLong_fits_in_16_bits ( ULong u )
675436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov{
676436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   Long i = u & 0xFFFFULL;
677436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   i <<= 48;
678436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   i >>= 48;
679436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   return toBool(u == (ULong) i);
680436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov}
681436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
682436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstatic Bool uLong_is_4_aligned ( ULong u )
683436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov{
684436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   return toBool((u & 3ULL) == 0);
685436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov}
686436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
687663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic Bool sane_AMode(ISelEnv * env, MIPSAMode * am)
688663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
689663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   switch (am->tag) {
690663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Mam_IR:
691663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         return toBool(hregClass(am->Mam.IR.base) == HRcGPR(mode64) &&
692663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  hregIsVirtual(am->Mam.IR.base) &&
693663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  uInt_fits_in_16_bits(am->Mam.IR.index));
694663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Mam_RR:
695663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         return toBool(hregClass(am->Mam.RR.base) == HRcGPR(mode64) &&
696663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  hregIsVirtual(am->Mam.RR.base) &&
697663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  hregClass(am->Mam.RR.index) == HRcGPR(mode64) &&
698436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                  hregIsVirtual(am->Mam.RR.index));
699663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      default:
700663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         vpanic("sane_AMode: unknown mips amode tag");
701663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
702663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
703663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
704663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic MIPSAMode *iselWordExpr_AMode(ISelEnv * env, IRExpr * e, IRType xferTy)
705663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
706663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   MIPSAMode *am = iselWordExpr_AMode_wrk(env, e, xferTy);
707663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vassert(sane_AMode(env, am));
708663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return am;
709663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
710663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
711663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* DO NOT CALL THIS DIRECTLY ! */
712663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic MIPSAMode *iselWordExpr_AMode_wrk(ISelEnv * env, IRExpr * e,
713436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                         IRType xferTy)
714663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
715663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRType ty = typeOfIRExpr(env->type_env, e);
716436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   if (env->mode64) {
717436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      Bool aligned4imm = toBool(xferTy == Ity_I32 || xferTy == Ity_I64);
718436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      vassert(ty == Ity_I64);
719436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
720436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      /* Add64(expr,i), where i == sign-extend of (i & 0xFFFF) */
721436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      if (e->tag == Iex_Binop && e->Iex.Binop.op == Iop_Add64
722436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov          && e->Iex.Binop.arg2->tag == Iex_Const
723436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov          && e->Iex.Binop.arg2->Iex.Const.con->tag == Ico_U64
724436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov          && (aligned4imm ?
725436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov          uLong_is_4_aligned(e->Iex.Binop.arg2->Iex.Const.con->Ico.U64) : True)
726436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov          && uLong_fits_in_16_bits(e->Iex.Binop.arg2->Iex.Const.con->Ico.U64)) {
727436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         return MIPSAMode_IR((Int) e->Iex.Binop.arg2->Iex.Const.con->Ico.U64,
728436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                   iselWordExpr_R(env, e->Iex.Binop.arg1));
729436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      }
730436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
731436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      /* Add64(expr,expr) */
732436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      if (e->tag == Iex_Binop && e->Iex.Binop.op == Iop_Add64) {
733436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         HReg r_base = iselWordExpr_R(env, e->Iex.Binop.arg1);
734436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         HReg r_idx = iselWordExpr_R(env, e->Iex.Binop.arg2);
735436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         return MIPSAMode_RR(r_idx, r_base);
736436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      }
737436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   } else {
738663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      vassert(ty == Ity_I32);
739663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
740663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* Add32(expr,i), where i == sign-extend of (i & 0xFFFF) */
741663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (e->tag == Iex_Binop
742663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          && e->Iex.Binop.op == Iop_Add32
743663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          && e->Iex.Binop.arg2->tag == Iex_Const
744663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          && e->Iex.Binop.arg2->Iex.Const.con->tag == Ico_U32
745663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          && uInt_fits_in_16_bits(e->Iex.Binop.arg2->Iex.Const.con-> Ico.U32)) {
746663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         return MIPSAMode_IR((Int) e->Iex.Binop.arg2->Iex.Const.con->Ico.U32,
747663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                              iselWordExpr_R(env, e->Iex.Binop.arg1));
748663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
749663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
750663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* Add32(expr,expr) */
751663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (e->tag == Iex_Binop && e->Iex.Binop.op == Iop_Add32) {
752663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         HReg r_base = iselWordExpr_R(env, e->Iex.Binop.arg1);
753663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         HReg r_idx = iselWordExpr_R(env, e->Iex.Binop.arg2);
754663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
755663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         return MIPSAMode_RR(r_idx, r_base);
756663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
757663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
758663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
759663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* Doesn't match anything in particular.  Generate it into
760663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      a register and use that. */
761663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return MIPSAMode_IR(0, iselWordExpr_R(env, e));
762663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
763663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
764663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/*---------------------------------------------------------*/
765663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/*--- ISEL: Integer expressions (64/32/16/8 bit)        ---*/
766663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/*---------------------------------------------------------*/
767663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
768663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* Select insns for an integer-typed expression, and add them to the
769663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   code list.  Return a reg holding the result.  This reg will be a
770663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   virtual register.  THE RETURNED REG MUST NOT BE MODIFIED.  If you
771663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   want to modify it, ask for a new vreg, copy it in there, and modify
772663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   the copy.  The register allocator will do its best to map both
773663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vregs to the same real register, so the copies will often disappear
774663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   later in the game.
775663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
776663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   This should handle expressions of 64, 32, 16 and 8-bit type.
777663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   All results are returned in a (mode64 ? 64bit : 32bit) register.
778663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   For 16- and 8-bit expressions, the upper (32/48/56 : 16/24) bits
779663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   are arbitrary, so you should mask or sign extend partial values
780663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if necessary.
781663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng*/
782663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic HReg iselWordExpr_R(ISelEnv * env, IRExpr * e)
783663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
784663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   HReg r = iselWordExpr_R_wrk(env, e);
785663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* sanity checks ... */
786663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
787663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vassert(hregClass(r) == HRcGPR(env->mode64));
788663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vassert(hregIsVirtual(r));
789663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return r;
790663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
791663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
792663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* DO NOT CALL THIS DIRECTLY ! */
793663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic HReg iselWordExpr_R_wrk(ISelEnv * env, IRExpr * e)
794663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
795436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   UInt argiregs = 0;
796663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRType ty = typeOfIRExpr(env->type_env, e);
797663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vassert(ty == Ity_I8 || ty == Ity_I16 || ty == Ity_I32 || ty == Ity_I1
798663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng           || ty == Ity_F32 || (ty == Ity_I64 && mode64)
799663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng           || (ty == Ity_I128 && mode64));
800663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
801663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   switch (e->tag) {
802663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* --------- TEMP --------- */
803663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Iex_RdTmp:
804663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         return lookupIRTemp(env, e->Iex.RdTmp.tmp);
805663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
806663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* --------- LOAD --------- */
807663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Iex_Load: {
808663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         HReg r_dst = newVRegI(env);
809663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         MIPSAMode *am_addr = iselWordExpr_AMode(env, e->Iex.Load.addr, ty);
810663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
811663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (e->Iex.Load.end != Iend_LE
812663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng             && e->Iex.Load.end != Iend_BE)
813663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            goto irreducible;
814663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
815663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         addInstr(env, MIPSInstr_Load(toUChar(sizeofIRType(ty)),
816663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                      r_dst, am_addr, mode64));
817663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         return r_dst;
818663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
819663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
820663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* --------- BINARY OP --------- */
821663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Iex_Binop: {
822663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         MIPSAluOp aluOp;
823663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         MIPSShftOp shftOp;
824663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
825663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* Is it an addition or logical style op? */
826663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         switch (e->Iex.Binop.op) {
827436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            case Iop_Add8:
828436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            case Iop_Add16:
829663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            case Iop_Add32:
830663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               aluOp = Malu_ADD;
831663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               break;
832436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
833663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            case Iop_Sub8:
834663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            case Iop_Sub16:
835663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            case Iop_Sub32:
836663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               aluOp = Malu_SUB;
837663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               break;
838436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
839436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            case Iop_Sub64:
840436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               aluOp = Malu_DSUB;
841436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               break;
842436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
843436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            case Iop_And8:
844436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            case Iop_And16:
845663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            case Iop_And32:
846663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            case Iop_And64:
847663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               aluOp = Malu_AND;
848663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               break;
849436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
850436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            case Iop_Or8:
851436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            case Iop_Or16:
852663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            case Iop_Or32:
853663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            case Iop_Or64:
854663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               aluOp = Malu_OR;
855663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               break;
856436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
857436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            case Iop_Xor8:
858436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            case Iop_Xor16:
859663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            case Iop_Xor32:
860663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            case Iop_Xor64:
861663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               aluOp = Malu_XOR;
862663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               break;
863436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
864436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            case Iop_Add64:
865436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               aluOp = Malu_DADD;
866436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               break;
867436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
868663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            default:
869663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               aluOp = Malu_INVALID;
870663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               break;
871663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
872663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
873663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* For commutative ops we assume any literal
874663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            values are on the second operand. */
875663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (aluOp != Malu_INVALID) {
876663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            HReg r_dst = newVRegI(env);
877663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            HReg r_srcL = iselWordExpr_R(env, e->Iex.Binop.arg1);
878663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            MIPSRH *ri_srcR = NULL;
879663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            /* get right arg into an RH, in the appropriate way */
880663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            switch (aluOp) {
881663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               case Malu_ADD:
882663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               case Malu_SUB:
883436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               case Malu_DADD:
884436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               case Malu_DSUB:
885663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  ri_srcR = iselWordExpr_RH(env, True /*signed */ ,
886663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                            e->Iex.Binop.arg2);
887663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  break;
888663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               case Malu_AND:
889663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               case Malu_OR:
890663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               case Malu_XOR:
891663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  ri_srcR = iselWordExpr_RH(env, False /*unsigned */,
892663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                            e->Iex.Binop.arg2);
893663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  break;
894663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               default:
895663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  vpanic("iselWordExpr_R_wrk-aluOp-arg2");
896663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            }
897663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addInstr(env, MIPSInstr_Alu(aluOp, r_dst, r_srcL, ri_srcR));
898663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            return r_dst;
899663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
900663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
901663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* a shift? */
902663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         switch (e->Iex.Binop.op) {
903663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            case Iop_Shl32:
904663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            case Iop_Shl64:
905663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               shftOp = Mshft_SLL;
906663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               break;
907663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            case Iop_Shr32:
908663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            case Iop_Shr64:
909663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               shftOp = Mshft_SRL;
910663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               break;
911663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            case Iop_Sar32:
912663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            case Iop_Sar64:
913663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               shftOp = Mshft_SRA;
914663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               break;
915663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            default:
916663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               shftOp = Mshft_INVALID;
917663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               break;
918663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
919663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
920663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* we assume any literal values are on the second operand. */
921663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (shftOp != Mshft_INVALID) {
922663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            HReg r_dst = newVRegI(env);
923663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            HReg r_srcL = iselWordExpr_R(env, e->Iex.Binop.arg1);
924436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            MIPSRH *ri_srcR;
925436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            if (mode64)
926436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               ri_srcR = iselWordExpr_RH6u(env, e->Iex.Binop.arg2);
927436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            else
928436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               ri_srcR = iselWordExpr_RH5u(env, e->Iex.Binop.arg2);
929436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
930436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            if (ty == Ity_I8) {
931436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               vassert(0);
932436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            } else if (ty == Ity_I32) {
933436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               if (mode64 && (shftOp == Mshft_SRA || shftOp == Mshft_SRL)) {
934436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                  HReg tmp = newVRegI(env);
935436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                  HReg r_srcL_se = newVRegI(env);
936436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                  /* SRA, SRAV, SRL, SRLV: On 64-bit processors, if GPR rt does
937436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                     not contain a sign-extended 32-bit value (bits 63..31
938436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                     equal), then the result of the operation is UNPREDICTABLE.
939436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                     So we need to sign-extend r_srcL:
940436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                     DSLLV tmp, r_srcL, 32
941436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                     DSRAV r_srcL_se, tmp, 32
942436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                  */
943436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                  addInstr(env, MIPSInstr_Shft(Mshft_SLL, False, tmp,
944436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                               r_srcL, MIPSRH_Imm(False, 32)));
945436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                  addInstr(env, MIPSInstr_Shft(Mshft_SRA, False, r_srcL_se,
946436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                               tmp, MIPSRH_Imm(False, 32)));
947436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                  /* And finally do the shift. */
948436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                  addInstr(env, MIPSInstr_Shft(shftOp, True /*32bit shift */,
949436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                               r_dst, r_srcL_se, ri_srcR));
950436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               } else
951436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                  addInstr(env, MIPSInstr_Shft(shftOp, True /*32bit shift */,
952436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                               r_dst, r_srcL, ri_srcR));
953436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            } else if (ty == Ity_I64) {
954663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               vassert(mode64);
955663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               addInstr(env, MIPSInstr_Shft(shftOp, False/*64bit shift */,
956663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                            r_dst, r_srcL, ri_srcR));
957436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            } else
958436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               goto irreducible;
959663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            return r_dst;
960663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
961663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
962663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* Cmp*32*(x,y) ? */
963663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (e->Iex.Binop.op == Iop_CmpEQ32
964436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov             || e->Iex.Binop.op == Iop_CmpEQ16
965663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng             || e->Iex.Binop.op == Iop_CmpNE32
966663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng             || e->Iex.Binop.op == Iop_CmpNE64
967663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng             || e->Iex.Binop.op == Iop_CmpLT32S
968663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng             || e->Iex.Binop.op == Iop_CmpLT32U
969663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng             || e->Iex.Binop.op == Iop_CmpLT64U
970436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov             || e->Iex.Binop.op == Iop_CmpLE32U
971663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng             || e->Iex.Binop.op == Iop_CmpLE32S
972663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng             || e->Iex.Binop.op == Iop_CmpLE64S
973663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng             || e->Iex.Binop.op == Iop_CmpLT64S
974663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng             || e->Iex.Binop.op == Iop_CmpEQ64) {
975663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
976663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            Bool syned = (e->Iex.Binop.op == Iop_CmpLT32S
977663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                         || e->Iex.Binop.op == Iop_CmpLE32S
978663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                         || e->Iex.Binop.op == Iop_CmpLT64S
979663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                         || e->Iex.Binop.op == Iop_CmpLE64S);
980663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            Bool size32;
981663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            HReg dst = newVRegI(env);
982663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            HReg r1 = iselWordExpr_R(env, e->Iex.Binop.arg1);
983663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            HReg r2 = iselWordExpr_R(env, e->Iex.Binop.arg2);
984663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
985663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            MIPSCondCode cc;
986663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
987663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            switch (e->Iex.Binop.op) {
988663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               case Iop_CmpEQ32:
989663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  cc = MIPScc_EQ;
990663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  size32 = True;
991663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  break;
992436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               case Iop_CmpEQ16:
993436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                  cc = MIPScc_EQ;
994436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                  size32 = True;
995436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                  break;
996663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               case Iop_CmpNE32:
997663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  cc = MIPScc_NE;
998663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  size32 = True;
999663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  break;
1000663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               case Iop_CmpNE64:
1001663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  cc = MIPScc_NE;
1002663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  size32 = True;
1003663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  break;
1004663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               case Iop_CmpLT32S:
1005663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  cc = MIPScc_LT;
1006663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  size32 = True;
1007663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  break;
1008663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               case Iop_CmpLT32U:
1009663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  cc = MIPScc_LO;
1010663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  size32 = True;
1011663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  break;
1012663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               case Iop_CmpLT64U:
1013663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  cc = MIPScc_LO;
1014663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  size32 = False;
1015663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  break;
1016436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               case Iop_CmpLE32U:
1017436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                  cc = MIPScc_LE;
1018436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                  size32 = True;
1019436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                  break;
1020663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               case Iop_CmpLE32S:
1021663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  cc = MIPScc_LE;
1022663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  size32 = True;
1023663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  break;
1024663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               case Iop_CmpLE64S:
1025663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  cc = MIPScc_LE;
1026663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  size32 = False;
1027663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  break;
1028663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               case Iop_CmpLT64S:
1029663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  cc = MIPScc_LT;
1030663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  size32 = False;
1031663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  break;
1032663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               case Iop_CmpEQ64:
1033663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  cc = MIPScc_EQ;
1034663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  size32 = False;
1035663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  break;
1036663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               default:
1037436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                  vpanic("iselCondCode(mips): CmpXX32 or CmpXX64");
1038663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            }
1039663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
1040663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addInstr(env, MIPSInstr_Cmp(syned, size32, dst, r1, r2, cc));
1041663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            return dst;
1042663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
1043663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
1044663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (e->Iex.Binop.op == Iop_Max32U) {
1045436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            HReg tmp = newVRegI(env);
1046436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            HReg r_dst = newVRegI(env);
1047663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            HReg argL = iselWordExpr_R(env, e->Iex.Binop.arg1);
1048436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            HReg argR = iselWordExpr_R(env, e->Iex.Binop.arg2);
1049436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            MIPSRH *argRH = iselWordExpr_RH(env, False /*signed */ ,
1050663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                           e->Iex.Binop.arg2);
1051436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            /* max (v0, s0)
1052436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               ------------
1053436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               slt v1, v0, s0
1054436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               movn v0, s0, v1 */
1055436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
1056436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            addInstr(env, MIPSInstr_Alu(Malu_SLT, tmp, argL, argRH));
1057436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            addInstr(env, mk_iMOVds_RR(r_dst, argL));
1058436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            addInstr(env, MIPSInstr_MoveCond(MMoveCond_movn, r_dst, argR, tmp));
1059436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            return r_dst;
1060663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
1061663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
1062663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (e->Iex.Binop.op == Iop_Mul32 || e->Iex.Binop.op == Iop_Mul64) {
1063663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            Bool sz32 = (e->Iex.Binop.op == Iop_Mul32);
1064663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            HReg r_dst = newVRegI(env);
1065663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            HReg r_srcL = iselWordExpr_R(env, e->Iex.Binop.arg1);
1066663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            HReg r_srcR = iselWordExpr_R(env, e->Iex.Binop.arg2);
1067663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addInstr(env, MIPSInstr_Mul(False/*Unsigned or Signed */ ,
1068663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                       False /*widen */ ,
1069663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                       sz32 /*32bit or 64bit */,
1070663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                       r_dst, r_srcL, r_srcR));
1071663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            return r_dst;
1072663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
1073663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
1074663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (e->Iex.Binop.op == Iop_MullU32 || e->Iex.Binop.op == Iop_MullS32) {
1075663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            HReg r_dst = newVRegI(env);
1076663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            HReg tHi = newVRegI(env);
1077663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            HReg tLo = newVRegI(env);
1078663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            HReg tLo_1 = newVRegI(env);
1079663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            HReg tHi_1 = newVRegI(env);
1080663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            HReg mask = newVRegI(env);
1081663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
1082663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            Bool syned = toBool(e->Iex.Binop.op == Iop_MullS32);
1083663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            Bool size = toBool(e->Iex.Binop.op == Iop_MullS32)
1084663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                        || toBool(e->Iex.Binop.op == Iop_MullU32);
1085663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            HReg r_srcL = iselWordExpr_R(env, e->Iex.Binop.arg1);
1086663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            HReg r_srcR = iselWordExpr_R(env, e->Iex.Binop.arg2);
1087663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addInstr(env, MIPSInstr_Mul(syned /*Unsigned or Signed */ ,
1088663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                        True /*widen */ ,
1089663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                        size /*32bit or 64bit mul */ ,
1090663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                        r_dst, r_srcL, r_srcR));
1091663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
1092663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addInstr(env, MIPSInstr_Mfhi(tHi));
1093663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addInstr(env, MIPSInstr_Mflo(tLo));
1094663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
1095663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addInstr(env, MIPSInstr_Shft(Mshft_SLL, False, tHi_1,
1096663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                          tHi, MIPSRH_Imm(False, 32)));
1097663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
1098663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addInstr(env, MIPSInstr_LI(mask, 0xffffffff));
1099663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addInstr(env, MIPSInstr_Alu(Malu_AND, tLo_1, tLo,
1100663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                          MIPSRH_Reg(mask)));
1101663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
1102663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addInstr(env, MIPSInstr_Alu(Malu_OR, r_dst, tHi_1,
1103663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                          MIPSRH_Reg(tLo_1)));
1104663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
1105663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            return r_dst;
1106663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
1107663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
1108663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (e->Iex.Binop.op == Iop_CmpF64) {
1109663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            HReg r_srcL, r_srcR;
1110436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            if (mode64) {
1111436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               r_srcL = iselFltExpr(env, e->Iex.Binop.arg1);
1112436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               r_srcR = iselFltExpr(env, e->Iex.Binop.arg2);
1113436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            } else {
1114663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               r_srcL = iselDblExpr(env, e->Iex.Binop.arg1);
1115663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               r_srcR = iselDblExpr(env, e->Iex.Binop.arg2);
1116663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            }
1117663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            HReg tmp = newVRegI(env);
1118663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            HReg r_ccMIPS = newVRegI(env);
1119663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            HReg r_ccIR = newVRegI(env);
1120663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            HReg r_ccIR_b0 = newVRegI(env);
1121663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            HReg r_ccIR_b2 = newVRegI(env);
1122663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            HReg r_ccIR_b6 = newVRegI(env);
1123663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
1124663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            /* Create in dst, the IRCmpF64Result encoded result. */
1125436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            /* chech for EQ */
1126436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            addInstr(env, MIPSInstr_FpCompare(Mfp_CMP_EQ, tmp, r_srcL, r_srcR));
1127436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            addInstr(env, MIPSInstr_Shft(Mshft_SLL, True, r_ccMIPS, tmp,
1128436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                         MIPSRH_Imm(False, 1)));
1129436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            /* chech for UN */
1130436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            addInstr(env, MIPSInstr_FpCompare(Mfp_CMP_UN, tmp, r_srcL, r_srcR));
1131663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addInstr(env, MIPSInstr_Alu(Malu_OR, r_ccMIPS, r_ccMIPS,
1132663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                        MIPSRH_Reg(tmp)));
1133436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            /* chech for LT */
1134436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            addInstr(env, MIPSInstr_FpCompare(Mfp_CMP_LT, tmp, r_srcL, r_srcR));
1135436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            addInstr(env, MIPSInstr_Shft(Mshft_SLL, True, tmp,
1136436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                         tmp, MIPSRH_Imm(False, 2)));
1137663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addInstr(env, MIPSInstr_Alu(Malu_OR, r_ccMIPS, r_ccMIPS,
1138663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                        MIPSRH_Reg(tmp)));
1139436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            /* chech for GT */
1140436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            addInstr(env, MIPSInstr_FpCompare(Mfp_CMP_NGT,
1141436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                              tmp, r_srcL, r_srcR));
1142436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            addInstr(env, MIPSInstr_Shft(Mshft_SLL, True, tmp, tmp,
1143436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                         MIPSRH_Imm(False, 3)));
1144663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
1145663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addInstr(env, MIPSInstr_Alu(Malu_NOR, tmp, tmp, MIPSRH_Reg(tmp)));
1146663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addInstr(env, MIPSInstr_Alu(Malu_AND, tmp, tmp,
1147663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                        MIPSRH_Imm(False, 8)));
1148663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addInstr(env, MIPSInstr_Alu(Malu_OR, r_ccMIPS, r_ccMIPS,
1149663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                        MIPSRH_Reg(tmp)));
1150436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            /* Map compare result from MIPS to IR,
1151436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               conforming to CmpF64 definition.
1152663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               FP cmp result | MIPS | IR
1153663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               --------------------------
1154663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               UN            | 0x1 | 0x45
1155663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               EQ            | 0x2 | 0x40
1156663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               GT            | 0x4 | 0x00
1157663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               LT            | 0x8 | 0x01
1158663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng             */
1159663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
1160436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            /* r_ccIR_b0 = r_ccMIPS[0] | r_ccMIPS[3] */
1161663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addInstr(env, MIPSInstr_Shft(Mshft_SRL, True, r_ccIR_b0, r_ccMIPS,
1162663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                          MIPSRH_Imm(False, 0x3)));
1163663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addInstr(env, MIPSInstr_Alu(Malu_OR, r_ccIR_b0, r_ccMIPS,
1164663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                          MIPSRH_Reg(r_ccIR_b0)));
1165663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addInstr(env, MIPSInstr_Alu(Malu_AND, r_ccIR_b0, r_ccIR_b0,
1166663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                          MIPSRH_Imm(False, 0x1)));
1167663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
1168436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            /* r_ccIR_b2 = r_ccMIPS[0] */
1169663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addInstr(env, MIPSInstr_Shft(Mshft_SLL, True, r_ccIR_b2, r_ccMIPS,
1170663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                          MIPSRH_Imm(False, 0x2)));
1171663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addInstr(env, MIPSInstr_Alu(Malu_AND, r_ccIR_b2, r_ccIR_b2,
1172663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                          MIPSRH_Imm(False, 0x4)));
1173663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
1174436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            /* r_ccIR_b6 = r_ccMIPS[0] | r_ccMIPS[1] */
1175663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addInstr(env, MIPSInstr_Shft(Mshft_SRL, True, r_ccIR_b6,
1176663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                          r_ccMIPS, MIPSRH_Imm(False, 0x1)));
1177663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addInstr(env, MIPSInstr_Alu(Malu_OR, r_ccIR_b6, r_ccMIPS,
1178663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                          MIPSRH_Reg(r_ccIR_b6)));
1179663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addInstr(env, MIPSInstr_Shft(Mshft_SLL, True, r_ccIR_b6, r_ccIR_b6,
1180663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                          MIPSRH_Imm(False, 0x6)));
1181663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addInstr(env, MIPSInstr_Alu(Malu_AND, r_ccIR_b6, r_ccIR_b6,
1182663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                          MIPSRH_Imm(False, 0x40)));
1183663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
1184436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            /* r_ccIR = r_ccIR_b0 | r_ccIR_b2 | r_ccIR_b6 */
1185663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addInstr(env, MIPSInstr_Alu(Malu_OR, r_ccIR, r_ccIR_b0,
1186663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                          MIPSRH_Reg(r_ccIR_b2)));
1187663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addInstr(env, MIPSInstr_Alu(Malu_OR, r_ccIR, r_ccIR,
1188663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                          MIPSRH_Reg(r_ccIR_b6)));
1189663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            return r_ccIR;
1190663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
1191663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
1192663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (e->Iex.Binop.op == Iop_DivModU64to32 ||
1193663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng             e->Iex.Binop.op == Iop_DivModS64to32) {
1194663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            HReg tLo = newVRegI(env);
1195663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            HReg tHi = newVRegI(env);
1196663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            HReg mask = newVRegI(env);
1197663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            HReg tLo_1 = newVRegI(env);
1198663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            HReg tHi_1 = newVRegI(env);
1199663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            HReg r_dst = newVRegI(env);
1200663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            Bool syned = toBool(e->Iex.Binop.op == Iop_DivModS64to32);
1201663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
1202663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            HReg r_srcR = iselWordExpr_R(env, e->Iex.Binop.arg2);
1203663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            HReg r_srcL = iselWordExpr_R(env, e->Iex.Binop.arg1);
1204663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
1205663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addInstr(env, MIPSInstr_Div(syned, True, r_srcL, r_srcR));
1206663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addInstr(env, MIPSInstr_Mfhi(tHi));
1207663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addInstr(env, MIPSInstr_Mflo(tLo));
1208663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
1209663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addInstr(env, MIPSInstr_Shft(Mshft_SLL, False, tHi_1, tHi,
1210663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                         MIPSRH_Imm(False, 32)));
1211663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
1212663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addInstr(env, MIPSInstr_LI(mask, 0xffffffff));
1213663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addInstr(env, MIPSInstr_Alu(Malu_AND, tLo_1, tLo,
1214663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                          MIPSRH_Reg(mask)));
1215663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
1216663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addInstr(env, MIPSInstr_Alu(Malu_OR, r_dst, tHi_1,
1217663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                          MIPSRH_Reg(tLo_1)));
1218663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
1219663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            return r_dst;
1220663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
1221663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
1222436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         if (e->Iex.Binop.op == Iop_8HLto16
1223436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov             || e->Iex.Binop.op == Iop_16HLto32) {
1224436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            HReg tHi   = iselWordExpr_R(env, e->Iex.Binop.arg1);
1225436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            HReg tLo   = iselWordExpr_R(env, e->Iex.Binop.arg2);
1226436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            HReg tLo_1 = newVRegI(env);
1227436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            HReg tHi_1 = newVRegI(env);
1228436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            HReg r_dst = newVRegI(env);
1229436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            UInt shift = 0;
1230436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            UInt mask  = 0;
1231436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            switch (e->Iex.Binop.op) {
1232436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               case Iop_8HLto16:
1233436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                  shift = 8;
1234436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                  mask  = 0xff;
1235436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                  break;
1236436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               case Iop_16HLto32:
1237436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                  shift = 16;
1238436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                  mask  = 0xffff;
1239436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                  break;
1240436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               default:
1241436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                  break;
1242436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            }
1243436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
1244436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            /* sll tHi_1, tHi,   shift
1245436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               and tLo_1, tLo,   mask
1246436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               or  r_dst, tHi_1, tLo_1 */
1247436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            addInstr(env, MIPSInstr_Shft(Mshft_SLL, True, tHi_1, tHi,
1248436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                         MIPSRH_Imm(False, shift)));
1249436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            addInstr(env, MIPSInstr_Alu(Malu_AND, tLo_1, tLo,
1250436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                          MIPSRH_Imm(False, mask)));
1251436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            addInstr(env, MIPSInstr_Alu(Malu_OR, r_dst, tHi_1,
1252436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                          MIPSRH_Reg(tLo_1)));
1253436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            return r_dst;
1254436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         }
1255436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
1256663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (e->Iex.Binop.op == Iop_32HLto64) {
1257663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            vassert(mode64);
1258663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            HReg tHi = iselWordExpr_R(env, e->Iex.Binop.arg1);
1259663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            HReg tLo = iselWordExpr_R(env, e->Iex.Binop.arg2);
1260663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            HReg tLo_1 = newVRegI(env);
1261663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            HReg tHi_1 = newVRegI(env);
1262663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            HReg r_dst = newVRegI(env);
1263663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            HReg mask = newVRegI(env);
1264663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
1265663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addInstr(env, MIPSInstr_Shft(Mshft_SLL, False, tHi_1, tHi,
1266663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                         MIPSRH_Imm(False, 32)));
1267663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
1268663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addInstr(env, MIPSInstr_LI(mask, 0xffffffff));
1269663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addInstr(env, MIPSInstr_Alu(Malu_AND, tLo_1, tLo,
1270663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                          MIPSRH_Reg(mask)));
1271663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addInstr(env, MIPSInstr_Alu(Malu_OR, r_dst, tHi_1,
1272663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                          MIPSRH_Reg(tLo_1)));
1273663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
1274663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            return r_dst;
1275663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
1276663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
1277436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         if (e->Iex.Binop.op == Iop_F32toI64S) {
1278436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            vassert(mode64);
1279436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            HReg valS = newVRegI(env);
1280436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            HReg tmpF = newVRegF(env);
1281436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            HReg valF = iselFltExpr(env, e->Iex.Binop.arg2);
1282436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
1283436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            /* CVTLS tmpF, valF */
1284436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            set_MIPS_rounding_mode(env, e->Iex.Binop.arg1);
1285436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            addInstr(env, MIPSInstr_FpConvert(Mfp_CVTLS, tmpF, valF));
1286436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            set_MIPS_rounding_default(env);
1287436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
1288436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            /* Doubleword Move from Floating Point
1289436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               dmfc1 valS, tmpF */
1290436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            addInstr(env, MIPSInstr_FpGpMove(MFpGpMove_dmfc1, valS, tmpF));
1291436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
1292436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            return valS;
1293436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         }
1294436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
1295663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (e->Iex.Binop.op == Iop_F64toI32S) {
1296436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            HReg valD;
1297436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            if (mode64)
1298436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               valD = iselFltExpr(env, e->Iex.Binop.arg2);
1299436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            else
1300436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               valD = iselDblExpr(env, e->Iex.Binop.arg2);
1301663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            HReg valS = newVRegF(env);
1302663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            HReg r_dst = newVRegI(env);
1303663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
1304436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            /* CVTWD valS, valD */
1305663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            set_MIPS_rounding_mode(env, e->Iex.Binop.arg1);
1306663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addInstr(env, MIPSInstr_FpConvert(Mfp_CVTWD, valS, valD));
1307663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            set_MIPS_rounding_default(env);
1308663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
1309436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            /* Move Word From Floating Point
1310436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               mfc1 r_dst, valS */
1311436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            addInstr(env, MIPSInstr_FpGpMove(MFpGpMove_mfc1, r_dst, valS));
1312663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
1313436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            return r_dst;
1314436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         }
1315663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
1316436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         /* -------- DSP ASE -------- */
1317436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         /* All used cases involving host-side helper calls. */
1318436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         void* fn = NULL;
1319436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         switch (e->Iex.Binop.op) {
1320436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            case Iop_HAdd8Ux4:
1321436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               fn = &h_generic_calc_HAdd8Ux4; break;
1322436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            case Iop_HSub8Ux4:
1323436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               fn = &h_generic_calc_HSub8Ux4; break;
1324436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            case Iop_HSub16Sx2:
1325436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               fn = &h_generic_calc_HSub16Sx2; break;
1326436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            case Iop_QSub8Ux4:
1327436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               fn = &h_generic_calc_QSub8Ux4; break;
1328436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            default:
1329436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                  break;
1330436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         }
1331663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
1332436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         /* What's the retloc? */
1333436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         RetLoc rloc = mk_RetLoc_INVALID();
1334436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         if (ty == Ity_I32) {
1335436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            rloc = mk_RetLoc_simple(RLPri_Int);
1336436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         }
1337436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         else if (ty == Ity_I64) {
1338436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            rloc = mode64 ? mk_RetLoc_simple(RLPri_Int) :
1339436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                            mk_RetLoc_simple(RLPri_2Int);
1340436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         }
1341436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         else {
1342436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            goto irreducible;
1343663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
1344663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
1345436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         if (fn) {
1346436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            HReg regL = iselWordExpr_R(env, e->Iex.Binop.arg1);
1347436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            HReg regR = iselWordExpr_R(env, e->Iex.Binop.arg2);
1348436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            HReg res  = newVRegI(env);
1349436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            addInstr(env, mk_iMOVds_RR(hregMIPS_GPR4(env->mode64), regL));
1350436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            addInstr(env, mk_iMOVds_RR(hregMIPS_GPR5(env->mode64), regR));
1351436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            argiregs |= (1 << 4);
1352436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            argiregs |= (1 << 5);
1353436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            addInstr(env, MIPSInstr_CallAlways( MIPScc_AL,
1354436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                                (HWord)Ptr_to_ULong(fn),
1355436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                                argiregs, rloc));
1356436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            addInstr(env, mk_iMOVds_RR(res, hregMIPS_GPR2(env->mode64)));
1357436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            return res;
1358436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         }
1359663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
1360663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
1361663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
1362436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   /* --------- UNARY OP --------- */
1363663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case Iex_Unop: {
1364663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      IROp op_unop = e->Iex.Unop.op;
1365663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
1366663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      switch (op_unop) {
1367436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         case Iop_1Sto8:
1368436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         case Iop_1Sto16:
1369663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case Iop_1Sto32:
1370436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         case Iop_8Sto16:
1371663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case Iop_8Sto32:
1372663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case Iop_16Sto32:
1373663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case Iop_16Sto64:
1374663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case Iop_8Sto64:
1375663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case Iop_1Sto64: {
1376663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            HReg r_dst = newVRegI(env);
1377663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            HReg r_src = iselWordExpr_R(env, e->Iex.Unop.arg);
1378663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            Bool sz32;
1379663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            UShort amt;
1380663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            switch (op_unop) {
1381436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               case Iop_1Sto8:
1382436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                  amt = 31;
1383436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                  sz32 = True;
1384436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                  break;
1385436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               case Iop_1Sto16:
1386436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                  amt = 31;
1387436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                  sz32 = True;
1388436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                  break;
1389663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               case Iop_1Sto32:
1390663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  amt = 31;
1391663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  sz32 = True;
1392663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  break;
1393663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               case Iop_16Sto32:
1394663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  amt = 16;
1395663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  sz32 = True;
1396663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  break;
1397663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               case Iop_16Sto64:
1398663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  amt = 48;
1399663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  sz32 = False;
1400663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  break;
1401436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               case Iop_8Sto16:
1402436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                  amt = 24;
1403436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                  sz32 = True;
1404436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                  break;
1405663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               case Iop_8Sto32:
1406663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  amt = 24;
1407663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  sz32 = True;
1408663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  break;
1409663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               case Iop_8Sto64:
1410663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  amt = 56;
1411663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  sz32 = False;
1412663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  break;
1413663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               case Iop_1Sto64:
1414663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  amt = 63;
1415663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  sz32 = False;
1416663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  break;
1417663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               default:
1418663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  vassert(0);
1419663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            }
1420663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
1421663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addInstr(env, MIPSInstr_Shft(Mshft_SLL, sz32, r_dst, r_src,
1422663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                         MIPSRH_Imm(False, amt)));
1423663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addInstr(env, MIPSInstr_Shft(Mshft_SRA, sz32, r_dst, r_dst,
1424663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                         MIPSRH_Imm(False, amt)));
1425663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            return r_dst;
1426663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
1427663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
1428436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         /* not(x) = nor(x,x) */
1429663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case Iop_Not1: {
1430663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            HReg r_dst = newVRegI(env);
1431663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            HReg r_srcL = iselWordExpr_R(env, e->Iex.Unop.arg);
1432663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            MIPSRH *r_srcR = MIPSRH_Reg(r_srcL);
1433663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
1434663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addInstr(env, MIPSInstr_LI(r_dst, 0x1));
1435663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addInstr(env, MIPSInstr_Alu(Malu_SUB, r_dst, r_dst, r_srcR));
1436663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            return r_dst;
1437663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
1438663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
1439436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         case Iop_Not8:
1440436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         case Iop_Not16:
1441663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case Iop_Not32:
1442663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case Iop_Not64: {
1443663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            HReg r_dst = newVRegI(env);
1444663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            HReg r_srcL = iselWordExpr_R(env, e->Iex.Unop.arg);
1445663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            MIPSRH *r_srcR = MIPSRH_Reg(r_srcL);
1446663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
1447663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addInstr(env, MIPSInstr_Alu(Malu_NOR, r_dst, r_srcL, r_srcR));
1448663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            return r_dst;
1449663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
1450663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
1451663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case Iop_ReinterpF32asI32: {
1452663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            HReg fr_src = iselFltExpr(env, e->Iex.Unop.arg);
1453663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            HReg r_dst = newVRegI(env);
1454663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
1455436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            /* Move Word From Floating Point
1456436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               mfc1 r_dst, fr_src */
1457436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            addInstr(env, MIPSInstr_FpGpMove(MFpGpMove_mfc1, r_dst, fr_src));
1458663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
1459663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            return r_dst;
1460663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
1461663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
1462663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case Iop_ReinterpF64asI64: {
1463663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            vassert(mode64);
1464663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            HReg fr_src = iselFltExpr(env, e->Iex.Unop.arg);
1465663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            HReg r_dst = newVRegI(env);
1466663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
1467436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            /* Doubleword Move from Floating Point
1468436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               mfc1 r_dst, fr_src */
1469436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            addInstr(env, MIPSInstr_FpGpMove(MFpGpMove_dmfc1, r_dst, fr_src));
1470663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
1471436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            return r_dst;
1472436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         }
1473436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
1474436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         case Iop_F64toI32S: {
1475436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            HReg valD;
1476436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            if (mode64)
1477436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               valD = iselFltExpr(env, e->Iex.Binop.arg2);
1478436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            else
1479436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               valD = iselDblExpr(env, e->Iex.Binop.arg2);
1480436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            HReg valS = newVRegF(env);
1481436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            HReg r_dst = newVRegI(env);
1482436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
1483436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            set_MIPS_rounding_mode(env, e->Iex.Binop.arg1);
1484436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            addInstr(env, MIPSInstr_FpConvert(Mfp_CVTWD, valS, valD));
1485436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            set_MIPS_rounding_default(env);
1486436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
1487436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            /* Move Word From Floating Point
1488436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               mfc1 r_dst, valS */
1489436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            addInstr(env, MIPSInstr_FpGpMove(MFpGpMove_mfc1, r_dst, valS));
1490663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
1491663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            return r_dst;
1492663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
1493663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
1494436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         case Iop_16to8:
1495436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         case Iop_32to1:
1496663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case Iop_32to8:
1497663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case Iop_32to16:
1498663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            return iselWordExpr_R(env, e->Iex.Unop.arg);
1499663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
1500436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         case Iop_32HIto16: {
1501436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            HReg r_dst = newVRegI(env);
1502436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            HReg r_src = iselWordExpr_R(env, e->Iex.Unop.arg);
1503436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            addInstr(env, MIPSInstr_Shft(Mshft_SRL, True /* 32bit shift */,
1504436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                         r_dst, r_src, MIPSRH_Imm(False, 16)));
1505436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            return r_dst;
1506436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         }
1507436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
1508436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         case Iop_64to1:
1509663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case Iop_64to8: {
1510663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            vassert(mode64);
1511663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            HReg r_src, r_dst;
1512436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            UShort mask = (op_unop == Iop_64to1) ? 0x1 : 0xFF;
1513663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            r_dst = newVRegI(env);
1514663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            r_src = iselWordExpr_R(env, e->Iex.Unop.arg);
1515663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addInstr(env, MIPSInstr_Alu(Malu_AND, r_dst, r_src,
1516436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                          MIPSRH_Imm(False, mask)));
1517663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            return r_dst;
1518663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
1519436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
1520436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         case Iop_16HIto8: {
1521436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            HReg r_dst = newVRegI(env);
1522436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            HReg r_src = iselWordExpr_R(env, e->Iex.Unop.arg);
1523436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            addInstr(env, MIPSInstr_Shft(Mshft_SRL, True /* 32bit shift */,
1524436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                         r_dst, r_src, MIPSRH_Imm(False, 8)));
1525436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            return r_dst;
1526436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         }
1527436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
1528436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         case Iop_1Uto8:
1529436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         case Iop_1Uto32:
1530436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         case Iop_1Uto64:
1531436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         case Iop_8Uto16:
1532663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case Iop_8Uto32:
1533436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         case Iop_8Uto64:
1534436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         case Iop_16Uto32:
1535436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         case Iop_16Uto64: {
1536663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            HReg r_dst = newVRegI(env);
1537663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            HReg r_src = iselWordExpr_R(env, e->Iex.Unop.arg);
1538436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            UShort mask = 0;
1539663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            switch (op_unop) {
1540436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               case Iop_1Uto64:
1541436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                  vassert(mode64);
1542663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               case Iop_1Uto8:
1543436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               case Iop_1Uto32:
1544436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                  mask = toUShort(0x1);
1545436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                  break;
1546436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               case Iop_8Uto64:
1547436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                  vassert(mode64);
1548436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               case Iop_8Uto16:
1549436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               case Iop_8Uto32:
1550436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                  mask = toUShort(0xFF);
1551663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  break;
1552436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               case Iop_16Uto64:
1553436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                  vassert(mode64);
1554663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               case Iop_16Uto32:
1555436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                  mask = toUShort(0xFFFF);
1556663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  break;
1557663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               default:
1558436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                  vassert(0);
1559663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  break;
1560663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            }
1561663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addInstr(env, MIPSInstr_Alu(Malu_AND, r_dst, r_src,
1562663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                          MIPSRH_Imm(False, mask)));
1563663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            return r_dst;
1564663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
1565663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
1566663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case Iop_32Uto64: {
1567663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            HReg r_dst = newVRegI(env);
1568663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            HReg r_src = iselWordExpr_R(env, e->Iex.Unop.arg);
1569663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            vassert(mode64);
1570436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            addInstr(env, MIPSInstr_Shft(Mshft_SLL, False /*!32bit shift */,
1571663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                         r_dst, r_src, MIPSRH_Imm(False, 32)));
1572436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            addInstr(env, MIPSInstr_Shft(Mshft_SRL, False /*!32bit shift */,
1573663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                         r_dst, r_dst, MIPSRH_Imm(False, 32)));
1574663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            return r_dst;
1575663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
1576663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
1577663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case Iop_64HIto32: {
1578436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            if (env->mode64) {
1579436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               HReg r_dst = newVRegI(env);
1580436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               HReg r_src = iselWordExpr_R(env, e->Iex.Unop.arg);
1581436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               addInstr(env, MIPSInstr_Shft(Mshft_SRA, False /*64bit shift */,
1582436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                       r_dst, r_src, MIPSRH_Imm(True, 32)));
1583436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               return r_dst;
1584436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            } else {
1585436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               HReg rHi, rLo;
1586436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               iselInt64Expr(&rHi, &rLo, env, e->Iex.Unop.arg);
1587436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               return rHi;
1588436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            }
1589663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
1590663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
1591663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case Iop_64to32: {
1592436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            if (env->mode64) {
1593436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               HReg r_dst = newVRegI(env);
1594436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               r_dst = iselWordExpr_R(env, e->Iex.Unop.arg);
1595436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               return r_dst;
1596436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            } else {
1597436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               HReg rHi, rLo;
1598436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               iselInt64Expr(&rHi, &rLo, env, e->Iex.Unop.arg);
1599436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               return rLo;
1600436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            }
1601663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
1602436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
1603663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case Iop_64to16: {
1604663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            vassert(env->mode64);
1605663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            HReg r_dst = newVRegI(env);
1606663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            r_dst = iselWordExpr_R(env, e->Iex.Unop.arg);
1607663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            return r_dst;
1608663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
1609436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
1610663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case Iop_32Sto64: {
1611663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            HReg r_dst = newVRegI(env);
1612663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            HReg r_src = iselWordExpr_R(env, e->Iex.Unop.arg);
1613663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            vassert(mode64);
1614436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            addInstr(env, MIPSInstr_Shft(Mshft_SLL, True /*!32bit shift */,
1615663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                         r_dst, r_src, MIPSRH_Imm(True, 0)));
1616663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            return r_dst;
1617663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
1618436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
1619436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         case Iop_CmpNEZ8:
1620436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         case Iop_CmpNEZ16: {
1621663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            HReg r_dst = newVRegI(env);
1622663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            HReg tmp = newVRegI(env);
1623663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            HReg r_src = iselWordExpr_R(env, e->Iex.Unop.arg);
1624436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            UShort mask = (op_unop == Iop_CmpNEZ8) ? 0xFF : 0xFFFF;
1625663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
1626663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addInstr(env, MIPSInstr_Alu(Malu_AND, tmp, r_src,
1627436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                        MIPSRH_Imm(False, mask)));
1628663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addInstr(env, MIPSInstr_Cmp(False, True, r_dst, tmp,
1629436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                        hregMIPS_GPR0(mode64), MIPScc_NE));
1630663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            return r_dst;
1631663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
1632663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
1633663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case Iop_CmpNEZ32: {
1634663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            HReg r_dst = newVRegI(env);
1635663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            HReg r_src = iselWordExpr_R(env, e->Iex.Unop.arg);
1636663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
1637663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addInstr(env, MIPSInstr_Cmp(False, True, r_dst, r_src,
1638436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                        hregMIPS_GPR0(mode64), MIPScc_NE));
1639663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            return r_dst;
1640663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
1641663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
1642663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case Iop_CmpwNEZ32: {
1643663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            HReg r_dst = newVRegI(env);
1644663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            HReg r_src = iselWordExpr_R(env, e->Iex.Unop.arg);
1645663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
1646663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addInstr(env, MIPSInstr_Alu(Malu_SUB, r_dst, hregMIPS_GPR0(mode64),
1647663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                          MIPSRH_Reg(r_src)));
1648663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
1649663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addInstr(env, MIPSInstr_Alu(Malu_OR, r_dst, r_dst,
1650663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                        MIPSRH_Reg(r_src)));
1651663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addInstr(env, MIPSInstr_Shft(Mshft_SRA, True, r_dst, r_dst,
1652663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                         MIPSRH_Imm(False, 31)));
1653663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            return r_dst;
1654663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
1655663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
1656663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case Iop_Left8:
1657436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         case Iop_Left16:
1658663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case Iop_Left32:
1659663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case Iop_Left64: {
1660663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            if (op_unop == Iop_Left64 && !mode64)
1661663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               goto irreducible;
1662663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            HReg r_dst = newVRegI(env);
1663663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            HReg r_src = iselWordExpr_R(env, e->Iex.Unop.arg);
1664436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            MIPSAluOp op = (op_unop == Iop_Left64) ? Malu_DSUB : Malu_SUB;
1665436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            addInstr(env, MIPSInstr_Alu(op, r_dst,
1666436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                        hregMIPS_GPR0(mode64),
1667436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                        MIPSRH_Reg(r_src)));
1668663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addInstr(env, MIPSInstr_Alu(Malu_OR, r_dst, r_dst,
1669663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                          MIPSRH_Reg(r_src)));
1670663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            return r_dst;
1671663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
1672663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
1673436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         case Iop_Clz64:
1674436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            vassert(mode64);
1675663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case Iop_Clz32: {
1676663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            HReg r_dst = newVRegI(env);
1677663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            HReg r_src = iselWordExpr_R(env, e->Iex.Unop.arg);
1678436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            MIPSUnaryOp op = (op_unop == Iop_Clz64) ? Mun_DCLZ : Mun_CLZ;
1679436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            addInstr(env, MIPSInstr_Unary(op, r_dst, r_src));
1680663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            return r_dst;
1681663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
1682663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
1683663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case Iop_CmpNEZ64: {
1684663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            HReg hi, lo;
1685663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            HReg r_dst = newVRegI(env);
1686663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            HReg r_src;
1687436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            if (env->mode64) {
1688436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               r_src = iselWordExpr_R(env, e->Iex.Unop.arg);
1689436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            } else {
1690436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               r_src = newVRegI(env);
1691436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               iselInt64Expr(&hi, &lo, env, e->Iex.Unop.arg);
1692436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               addInstr(env, MIPSInstr_Alu(Malu_OR, r_src, lo, MIPSRH_Reg(hi)));
1693436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            }
1694663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addInstr(env, MIPSInstr_Cmp(False, !(env->mode64), r_dst, r_src,
1695436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                        hregMIPS_GPR0(mode64), MIPScc_NE));
1696663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            return r_dst;
1697663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
1698663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
1699663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case Iop_CmpwNEZ64: {
1700663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            HReg tmp1;
1701663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            HReg tmp2 = newVRegI(env);
1702663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            vassert(env->mode64);
1703663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            tmp1 = iselWordExpr_R(env, e->Iex.Unop.arg);
1704663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
1705436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            addInstr(env, MIPSInstr_Alu(Malu_DSUB, tmp2, hregMIPS_GPR0(mode64),
1706663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                          MIPSRH_Reg(tmp1)));
1707663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
1708663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addInstr(env, MIPSInstr_Alu(Malu_OR, tmp2, tmp2, MIPSRH_Reg(tmp1)));
1709663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addInstr(env, MIPSInstr_Shft(Mshft_SRA, False, tmp2, tmp2,
1710663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                         MIPSRH_Imm (False, 63)));
1711663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            return tmp2;
1712663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
1713663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
1714663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case Iop_128HIto64: {
1715663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            vassert(mode64);
1716663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            HReg rHi, rLo;
1717663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            iselInt128Expr(&rHi, &rLo, env, e->Iex.Unop.arg);
1718436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            return rHi;  /* and abandon rLo .. poor wee thing :-) */
1719663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
1720663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
1721663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case Iop_128to64: {
1722663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            vassert(mode64);
1723663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            HReg rHi, rLo;
1724663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            iselInt128Expr(&rHi, &rLo, env, e->Iex.Unop.arg);
1725436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            return rLo;  /* and abandon rLo .. poor wee thing :-) */
1726663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
1727663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
1728663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         default:
1729663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            break;
1730663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
1731436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
1732436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      /* -------- DSP ASE -------- */
1733436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      /* All Unop cases involving host-side helper calls. */
1734436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      void* fn = NULL;
1735436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      switch (e->Iex.Unop.op) {
1736436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         case Iop_CmpNEZ16x2:
1737436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            fn = &h_generic_calc_CmpNEZ16x2; break;
1738436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         case Iop_CmpNEZ8x4:
1739436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            fn = &h_generic_calc_CmpNEZ8x4; break;
1740436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         default:
1741436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            break;
1742436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      }
1743436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
1744436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      RetLoc rloc = mk_RetLoc_INVALID();
1745436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      if (ty == Ity_I32) {
1746436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         rloc = mk_RetLoc_simple(RLPri_Int);
1747436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      }
1748436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      else if (ty == Ity_I64) {
1749436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         rloc = mode64 ? mk_RetLoc_simple(RLPri_Int) :
1750436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                         mk_RetLoc_simple(RLPri_2Int);
1751436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      }
1752436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      else {
1753436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         goto irreducible;
1754436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      }
1755436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
1756436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      if (fn) {
1757436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         HReg regL = iselWordExpr_R(env, e->Iex.Unop.arg);
1758436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         HReg res  = newVRegI(env);
1759436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         addInstr(env, mk_iMOVds_RR(hregMIPS_GPR4(env->mode64), regL));
1760436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         argiregs |= (1 << 4);
1761436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         addInstr(env, MIPSInstr_CallAlways( MIPScc_AL,
1762436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                             (HWord)Ptr_to_ULong(fn),
1763436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                             argiregs, rloc));
1764436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         addInstr(env, mk_iMOVds_RR(res, hregMIPS_GPR2(env->mode64)));
1765436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         return res;
1766436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      }
1767436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
1768663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
1769663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
1770663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
1771436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   /* --------- GET --------- */
1772663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case Iex_Get: {
1773663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (ty == Ity_I8 || ty == Ity_I16 || ty == Ity_I32
1774663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          || ((ty == Ity_I64) && mode64)) {
1775663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         HReg r_dst = newVRegI(env);
1776663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
1777663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         MIPSAMode *am_addr = MIPSAMode_IR(e->Iex.Get.offset,
1778663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                           GuestStatePointer(mode64));
1779663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         addInstr(env, MIPSInstr_Load(toUChar(sizeofIRType(ty)), r_dst, am_addr,
1780663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                      mode64));
1781663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         return r_dst;
1782663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
1783663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
1784663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
1785663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
1786436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   /* --------- ITE --------- */
1787436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   case Iex_ITE: {
1788663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if ((ty == Ity_I8 || ty == Ity_I16 ||
1789663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng           ty == Ity_I32 || ((ty == Ity_I64))) &&
1790436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov           typeOfIRExpr(env->type_env, e->Iex.ITE.cond) == Ity_I1) {
1791436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         HReg r_dst  = iselWordExpr_R(env, e->Iex.ITE.iffalse);
1792436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         HReg r1     = iselWordExpr_R(env, e->Iex.ITE.iftrue);
1793436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         HReg r_cond = iselWordExpr_R(env, e->Iex.ITE.cond);
1794663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /*
1795436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov          * r_dst = r0
1796436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov          * movn r_dst, r1, r_cond
1797663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          */
1798436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         addInstr(env, MIPSInstr_MoveCond(MMoveCond_movn, r_dst, r1, r_cond));
1799663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         return r_dst;
1800663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
1801663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
1802663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
1803663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
1804436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   /* --------- LITERAL --------- */
1805436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   /* 32/16/8-bit literals */
1806663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case Iex_Const: {
1807663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      Long l;
1808663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      HReg r_dst = newVRegI(env);
1809663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      IRConst *con = e->Iex.Const.con;
1810663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      switch (con->tag) {
1811663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case Ico_U64:
1812663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            if (!mode64)
1813663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               goto irreducible;
1814663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            l = (Long) con->Ico.U64;
1815663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            break;
1816663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case Ico_U32:
1817663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            l = (Long) (Int) con->Ico.U32;
1818663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            break;
1819663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case Ico_U16:
1820663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            l = (Long) (Int) (Short) con->Ico.U16;
1821663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            break;
1822663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case Ico_U8:
1823663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            l = (Long) (Int) (Char) con->Ico.U8;
1824663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            break;
1825663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         default:
1826663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            vpanic("iselIntExpr_R.const(mips)");
1827663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
1828663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      addInstr(env, MIPSInstr_LI(r_dst, (ULong) l));
1829663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      return r_dst;
1830663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
1831663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
1832436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   /* --------- CCALL --------- */
1833663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case Iex_CCall: {
1834663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      HReg r_dst = newVRegI(env);
1835663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      vassert(ty == e->Iex.CCall.retty);
1836663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
1837436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      /* be very restrictive for now.  Only 32/64-bit ints allowed for
1838436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         args, and 64 and 32 bits for return type.  Don't forget to change
1839436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         the RetLoc if more return types are allowed in future. */
1840436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      if (e->Iex.CCall.retty != Ity_I64 && e->Iex.CCall.retty != Ity_I32)
1841663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto irreducible;
1842663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
1843663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* Marshal args, do the call, clear stack. */
1844436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      UInt   addToSp = 0;
1845436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      RetLoc rloc    = mk_RetLoc_INVALID();
1846436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      doHelperCall(&addToSp, &rloc, env, NULL/*guard*/, e->Iex.CCall.cee,
1847436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                   e->Iex.CCall.retty, e->Iex.CCall.args );
1848436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
1849436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      vassert(is_sane_RetLoc(rloc));
1850436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      vassert(rloc.pri == RLPri_Int);
1851436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      vassert(addToSp == 0);
1852663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      addInstr(env, mk_iMOVds_RR(r_dst, hregMIPS_GPR2(mode64)));
1853663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      return r_dst;
1854663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
1855663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
1856663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   default:
1857663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
1858436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   }  /* end switch(e->tag) */
1859663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
1860663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* We get here if no pattern matched. */
1861663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   irreducible:
1862663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      vex_printf("--------------->\n");
1863663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (e->tag == Iex_RdTmp)
1864663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         vex_printf("Iex_RdTmp \n");
1865663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      ppIRExpr(e);
1866663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
1867663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      vpanic("iselWordExpr_R(mips): cannot reduce tree");
1868663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
1869663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
1870663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* --------------------- RH --------------------- */
1871663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
1872663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* Compute an I8/I16/I32 (and I64, in 64-bit mode) into a RH
1873663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   (reg-or-halfword-immediate).  It's important to specify whether the
1874663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   immediate is to be regarded as signed or not.  If yes, this will
1875663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   never return -32768 as an immediate; this guaranteed that all
1876663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   signed immediates that are return can have their sign inverted if
1877663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   need be. */
1878663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
1879663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic MIPSRH *iselWordExpr_RH(ISelEnv * env, Bool syned, IRExpr * e)
1880663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
1881663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   MIPSRH *ri = iselWordExpr_RH_wrk(env, syned, e);
1882663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* sanity checks ... */
1883663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   switch (ri->tag) {
1884663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Mrh_Imm:
1885663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         vassert(ri->Mrh.Imm.syned == syned);
1886663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (syned)
1887663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            vassert(ri->Mrh.Imm.imm16 != 0x8000);
1888663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         return ri;
1889663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Mrh_Reg:
1890663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         vassert(hregClass(ri->Mrh.Reg.reg) == HRcGPR(env->mode64));
1891663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         vassert(hregIsVirtual(ri->Mrh.Reg.reg));
1892663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         return ri;
1893663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      default:
1894663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         vpanic("iselIntExpr_RH: unknown mips RH tag");
1895663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
1896663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
1897663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
1898663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* DO NOT CALL THIS DIRECTLY ! */
1899663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic MIPSRH *iselWordExpr_RH_wrk(ISelEnv * env, Bool syned, IRExpr * e)
1900663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
1901663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   ULong u;
1902663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   Long l;
1903663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRType ty = typeOfIRExpr(env->type_env, e);
1904663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vassert(ty == Ity_I8 || ty == Ity_I16 || ty == Ity_I32 ||
1905663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          ((ty == Ity_I64) && env->mode64));
1906663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
1907663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* special case: immediate */
1908663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (e->tag == Iex_Const) {
1909663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      IRConst *con = e->Iex.Const.con;
1910663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* What value are we aiming to generate? */
1911663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      switch (con->tag) {
1912663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* Note: Not sign-extending - we carry 'syned' around */
1913663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case Ico_U64:
1914663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            vassert(env->mode64);
1915663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            u = con->Ico.U64;
1916663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            break;
1917663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case Ico_U32:
1918663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            u = 0xFFFFFFFF & con->Ico.U32;
1919663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            break;
1920663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case Ico_U16:
1921663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            u = 0x0000FFFF & con->Ico.U16;
1922663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            break;
1923663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case Ico_U8:
1924663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            u = 0x000000FF & con->Ico.U8;
1925663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            break;
1926663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         default:
1927663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            vpanic("iselIntExpr_RH.Iex_Const(mips)");
1928663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
1929663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      l = (Long) u;
1930663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* Now figure out if it's representable. */
1931663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (!syned && u <= 65535) {
1932663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         return MIPSRH_Imm(False /*unsigned */ , toUShort(u & 0xFFFF));
1933663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
1934663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (syned && l >= -32767 && l <= 32767) {
1935663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         return MIPSRH_Imm(True /*signed */ , toUShort(u & 0xFFFF));
1936663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
1937663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* no luck; use the Slow Way. */
1938663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
1939663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* default case: calculate into a register and return that */
1940663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return MIPSRH_Reg(iselWordExpr_R(env, e));
1941663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
1942663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
1943663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* --------------------- RH5u --------------------- */
1944663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
1945663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* Compute an I8 into a reg-or-5-bit-unsigned-immediate, the latter
1946663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   being an immediate in the range 1 .. 31 inclusive.  Used for doing
1947663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   shift amounts. */
1948663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
1949663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic MIPSRH *iselWordExpr_RH5u(ISelEnv * env, IRExpr * e)
1950663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
1951663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   MIPSRH *ri;
1952663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   ri = iselWordExpr_RH5u_wrk(env, e);
1953663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* sanity checks ... */
1954663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   switch (ri->tag) {
1955663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Mrh_Imm:
1956663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         vassert(ri->Mrh.Imm.imm16 >= 1 && ri->Mrh.Imm.imm16 <= 31);
1957663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         vassert(!ri->Mrh.Imm.syned);
1958663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         return ri;
1959663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Mrh_Reg:
1960663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         vassert(hregClass(ri->Mrh.Reg.reg) == HRcInt32);
1961663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         vassert(hregIsVirtual(ri->Mrh.Reg.reg));
1962663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         return ri;
1963663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      default:
1964663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         vpanic("iselIntExpr_RH5u: unknown mips RH tag");
1965663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
1966663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
1967663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
1968663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* DO NOT CALL THIS DIRECTLY ! */
1969663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic MIPSRH *iselWordExpr_RH5u_wrk(ISelEnv * env, IRExpr * e)
1970663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
1971663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRType ty = typeOfIRExpr(env->type_env, e);
1972663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vassert(ty == Ity_I8);
1973663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
1974663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* special case: immediate */
1975663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (e->tag == Iex_Const
1976663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng       && e->Iex.Const.con->tag == Ico_U8
1977663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng       && e->Iex.Const.con->Ico.U8 >= 1 && e->Iex.Const.con->Ico.U8 <= 31) {
1978663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      return MIPSRH_Imm(False /*unsigned */ , e->Iex.Const.con->Ico.U8);
1979663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
1980663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
1981663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* default case: calculate into a register and return that */
1982663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return MIPSRH_Reg(iselWordExpr_R(env, e));
1983663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
1984663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
1985436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov/* --------------------- RH6u --------------------- */
1986663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
1987436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov/* Only used in 64-bit mode. */
1988436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstatic MIPSRH *iselWordExpr_RH6u ( ISelEnv * env, IRExpr * e )
1989436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov{
1990436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   MIPSRH *ri;
1991436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   ri = iselWordExpr_RH6u_wrk(env, e);
1992436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   /* sanity checks ... */
1993436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   switch (ri->tag) {
1994436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   case Mrh_Imm:
1995436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      vassert(ri->Mrh.Imm.imm16 >= 1 && ri->Mrh.Imm.imm16 <= 63);
1996436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      vassert(!ri->Mrh.Imm.syned);
1997436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      return ri;
1998436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   case Mrh_Reg:
1999436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      vassert(hregClass(ri->Mrh.Reg.reg) == HRcGPR(env->mode64));
2000436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      vassert(hregIsVirtual(ri->Mrh.Reg.reg));
2001436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      return ri;
2002436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   default:
2003436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      vpanic("iselIntExpr_RH6u: unknown mips64 RI tag");
2004436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   }
2005436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov}
2006436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
2007436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov/* DO NOT CALL THIS DIRECTLY ! */
2008436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstatic MIPSRH *iselWordExpr_RH6u_wrk ( ISelEnv * env, IRExpr * e )
2009436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov{
2010436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   IRType ty = typeOfIRExpr(env->type_env, e);
2011436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   vassert(ty == Ity_I8);
2012436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
2013436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   /* special case: immediate */
2014436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   if (e->tag == Iex_Const
2015436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov       && e->Iex.Const.con->tag == Ico_U8
2016436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov       && e->Iex.Const.con->Ico.U8 >= 1 && e->Iex.Const.con->Ico.U8 <= 63)
2017436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   {
2018436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      return MIPSRH_Imm(False /*unsigned */ ,
2019436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov              e->Iex.Const.con->Ico.U8);
2020436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   }
2021436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
2022436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   /* default case: calculate into a register and return that */
2023436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   return MIPSRH_Reg(iselWordExpr_R(env, e));
2024436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov}
2025436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
2026436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov/* --------------------- CONDCODE --------------------- */
2027436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
2028436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov/* Generate code to evaluated a bit-typed expression, returning the
2029663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   condition code which would correspond when the expression would
2030663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   notionally have returned 1. */
2031663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
2032663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic MIPSCondCode iselCondCode(ISelEnv * env, IRExpr * e)
2033663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
2034663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   MIPSCondCode cc = iselCondCode_wrk(env,e);
2035663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vassert(cc != MIPScc_NV);
2036663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return cc;
2037663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
2038663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
2039663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* DO NOT CALL THIS DIRECTLY ! */
2040663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic MIPSCondCode iselCondCode_wrk(ISelEnv * env, IRExpr * e)
2041663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
2042663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vassert(e);
2043663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vassert(typeOfIRExpr(env->type_env, e) == Ity_I1);
2044663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* Cmp*32*(x,y) ? */
2045663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (e->Iex.Binop.op == Iop_CmpEQ32
2046663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng       || e->Iex.Binop.op == Iop_CmpNE32
2047663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng       || e->Iex.Binop.op == Iop_CmpNE64
2048663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng       || e->Iex.Binop.op == Iop_CmpLT32S
2049663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng       || e->Iex.Binop.op == Iop_CmpLT32U
2050663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng       || e->Iex.Binop.op == Iop_CmpLT64U
2051663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng       || e->Iex.Binop.op == Iop_CmpLE32S
2052663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng       || e->Iex.Binop.op == Iop_CmpLE64S
2053663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng       || e->Iex.Binop.op == Iop_CmpLT64S
2054663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng       || e->Iex.Binop.op == Iop_CmpEQ64) {
2055663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
2056663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      Bool syned = (e->Iex.Binop.op == Iop_CmpLT32S
2057663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                   || e->Iex.Binop.op == Iop_CmpLE32S
2058663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                   || e->Iex.Binop.op == Iop_CmpLT64S
2059663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                   || e->Iex.Binop.op == Iop_CmpLE64S);
2060663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      Bool size32;
2061663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      HReg dst = newVRegI(env);
2062663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      HReg r1 = iselWordExpr_R(env, e->Iex.Binop.arg1);
2063663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      HReg r2 = iselWordExpr_R(env, e->Iex.Binop.arg2);
2064663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
2065663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      MIPSCondCode cc;
2066663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
2067663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      switch (e->Iex.Binop.op) {
2068663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case Iop_CmpEQ32:
2069663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            cc = MIPScc_EQ;
2070663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            size32 = True;
2071663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            break;
2072663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case Iop_CmpNE32:
2073663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            cc = MIPScc_NE;
2074663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            size32 = True;
2075663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            break;
2076663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case Iop_CmpNE64:
2077663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            cc = MIPScc_NE;
2078663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            size32 = True;
2079663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            break;
2080663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case Iop_CmpLT32S:
2081663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            cc = MIPScc_LT;
2082663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            size32 = True;
2083663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            break;
2084663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case Iop_CmpLT32U:
2085663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            cc = MIPScc_LO;
2086663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            size32 = True;
2087663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            break;
2088663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case Iop_CmpLT64U:
2089663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            cc = MIPScc_LO;
2090663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            size32 = False;
2091663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            break;
2092663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case Iop_CmpLE32S:
2093663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            cc = MIPScc_LE;
2094663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            size32 = True;
2095663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            break;
2096663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case Iop_CmpLE64S:
2097663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            cc = MIPScc_LE;
2098663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            size32 = False;
2099663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            break;
2100663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case Iop_CmpLT64S:
2101663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            cc = MIPScc_LT;
2102663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            size32 = False;
2103663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            break;
2104663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case Iop_CmpEQ64:
2105663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            cc = MIPScc_EQ;
2106663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            size32 = False;
2107663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            break;
2108663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         default:
2109436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            vpanic("iselCondCode(mips): CmpXX32 or CmpXX64");
2110436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            break;
2111663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
2112663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
2113663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      addInstr(env, MIPSInstr_Cmp(syned, size32, dst, r1, r2, cc));
2114436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      /* Store result to guest_COND */
2115663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      MIPSAMode *am_addr = MIPSAMode_IR(0, GuestStatePointer(mode64));
2116663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
2117663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      addInstr(env, MIPSInstr_Store(4,
2118436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               MIPSAMode_IR(am_addr->Mam.IR.index + COND_OFFSET(mode64),
2119436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                            am_addr->Mam.IR.base),
2120663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               dst, mode64));
2121663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      return cc;
2122663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
2123663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (e->Iex.Binop.op == Iop_Not1) {
2124663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      HReg r_dst = newVRegI(env);
2125663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      HReg r_srcL = iselWordExpr_R(env, e->Iex.Unop.arg);
2126663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      MIPSRH *r_srcR = MIPSRH_Reg(r_srcL);
2127663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
2128663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      addInstr(env, MIPSInstr_LI(r_dst, 0x1));
2129663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      addInstr(env, MIPSInstr_Alu(Malu_SUB, r_dst, r_dst, r_srcR));
2130436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      /* Store result to guest_COND */
2131663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      MIPSAMode *am_addr = MIPSAMode_IR(0, GuestStatePointer(mode64));
2132663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
2133663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      addInstr(env, MIPSInstr_Store(4,
2134436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               MIPSAMode_IR(am_addr->Mam.IR.index + COND_OFFSET(mode64),
2135436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                            am_addr->Mam.IR.base),
2136663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               r_dst, mode64));
2137663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      return MIPScc_NE;
2138663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
2139663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (e->tag == Iex_RdTmp || e->tag == Iex_Unop) {
2140663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      HReg r_dst = iselWordExpr_R_wrk(env, e);
2141436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      /* Store result to guest_COND */
2142663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      MIPSAMode *am_addr = MIPSAMode_IR(0, GuestStatePointer(mode64));
2143663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
2144663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      addInstr(env, MIPSInstr_Store(4,
2145436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               MIPSAMode_IR(am_addr->Mam.IR.index + COND_OFFSET(mode64),
2146436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                            am_addr->Mam.IR.base),
2147663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               r_dst, mode64));
2148663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      return MIPScc_EQ;
2149663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
2150663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
2151663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vex_printf("iselCondCode(mips): No such tag(%u)\n", e->tag);
2152663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   ppIRExpr(e);
2153663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vpanic("iselCondCode(mips)");
2154663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
2155663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
2156663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/*---------------------------------------------------------*/
2157663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/*--- ISEL: Integer expressions (128 bit)               ---*/
2158663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/*---------------------------------------------------------*/
2159663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
2160663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* 64-bit mode ONLY: compute a 128-bit value into a register pair,
2161663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   which is returned as the first two parameters.  As with
2162663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   iselWordExpr_R, these may be either real or virtual regs; in any
2163663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case they must not be changed by subsequent code emitted by the
2164663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   caller.  */
2165663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
2166663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic void iselInt128Expr(HReg * rHi, HReg * rLo, ISelEnv * env, IRExpr * e)
2167663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
2168663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vassert(env->mode64);
2169663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   iselInt128Expr_wrk(rHi, rLo, env, e);
2170663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vassert(hregClass(*rHi) == HRcGPR(env->mode64));
2171663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vassert(hregIsVirtual(*rHi));
2172663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vassert(hregClass(*rLo) == HRcGPR(env->mode64));
2173663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vassert(hregIsVirtual(*rLo));
2174663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
2175663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
2176663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* DO NOT CALL THIS DIRECTLY ! */
2177663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic void iselInt128Expr_wrk(HReg * rHi, HReg * rLo, ISelEnv * env,
2178663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                               IRExpr * e)
2179663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
2180663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vassert(e);
2181663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vassert(typeOfIRExpr(env->type_env, e) == Ity_I128);
2182663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
2183663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* read 128-bit IRTemp */
2184663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (e->tag == Iex_RdTmp) {
2185663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      lookupIRTempPair(rHi, rLo, env, e->Iex.RdTmp.tmp);
2186663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      return;
2187663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
2188663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
2189663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* --------- BINARY ops --------- */
2190663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (e->tag == Iex_Binop) {
2191663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      switch (e->Iex.Binop.op) {
2192663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* 64 x 64 -> 128 multiply */
2193663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case Iop_MullU64:
2194436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         case Iop_MullS64: {
2195436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            HReg tLo = newVRegI(env);
2196436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            HReg tHi = newVRegI(env);
2197436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            Bool syned = toBool(e->Iex.Binop.op == Iop_MullS64);
2198436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            HReg r_dst = newVRegI(env);
2199436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            HReg r_srcL = iselWordExpr_R(env, e->Iex.Binop.arg1);
2200436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            HReg r_srcR = iselWordExpr_R(env, e->Iex.Binop.arg2);
2201436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            addInstr(env, MIPSInstr_Mul(syned, True, False /*64bit mul */ ,
2202436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                        r_dst, r_srcL, r_srcR));
2203436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            addInstr(env, MIPSInstr_Mfhi(tHi));
2204436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            addInstr(env, MIPSInstr_Mflo(tLo));
2205436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            *rHi = tHi;
2206436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            *rLo = tLo;
2207436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            return;
2208436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         }
2209436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
2210663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* 64HLto128(e1,e2) */
2211663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case Iop_64HLto128:
2212663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            *rHi = iselWordExpr_R(env, e->Iex.Binop.arg1);
2213663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            *rLo = iselWordExpr_R(env, e->Iex.Binop.arg2);
2214663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            return;
2215436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
2216663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case Iop_DivModS64to64: {
2217663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            HReg r_srcL = iselWordExpr_R(env, e->Iex.Binop.arg1);
2218663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            HReg r_srcR = iselWordExpr_R(env, e->Iex.Binop.arg2);
2219663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            HReg tLo = newVRegI(env);
2220663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            HReg tHi = newVRegI(env);
2221663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            Bool syned = toBool(e->Iex.Binop.op == Iop_DivModS64to64);
2222663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
2223663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addInstr(env, MIPSInstr_Div(syned, False, r_srcL, r_srcR));
2224663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addInstr(env, MIPSInstr_Mfhi(tHi));
2225663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addInstr(env, MIPSInstr_Mflo(tLo));
2226663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            *rHi = tHi;
2227663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            *rLo = tLo;
2228663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            return;
2229663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
2230436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
2231436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         case Iop_DivModU128to64:
2232436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         case Iop_DivModS128to64: {
2233663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            vassert(mode64);
2234663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            HReg rHi1, rLo1;
2235663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            iselInt128Expr(&rHi1, &rLo1, env, e->Iex.Binop.arg1);
2236663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
2237663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            HReg r_srcR = iselWordExpr_R(env, e->Iex.Binop.arg2);
2238663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            HReg tLo = newVRegI(env);
2239663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            HReg tHi = newVRegI(env);
2240663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            Bool syned = toBool(e->Iex.Binop.op == Iop_DivModS128to64);
2241663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
2242663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addInstr(env, MIPSInstr_Div(syned, False, rLo1, r_srcR));
2243663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addInstr(env, MIPSInstr_Mfhi(tHi));
2244663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addInstr(env, MIPSInstr_Mflo(tLo));
2245663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            *rHi = tHi;
2246663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            *rLo = tLo;
2247663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            return;
2248663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
2249436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
2250663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         default:
2251663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            break;
2252663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
2253663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
2254663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vex_printf("iselInt128Expr(mips64): No such tag(%u)\n", e->tag);
2255663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   ppIRExpr(e);
2256663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vpanic("iselInt128Expr(mips64)");
2257663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
2258663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
2259663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/*---------------------------------------------------------*/
2260663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/*--- ISEL: Integer expressions (64 bit)                ---*/
2261663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/*---------------------------------------------------------*/
2262663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
2263436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov/* 32-bit mode ONLY. Compute a 64-bit value into the register
2264663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng * pair HI, LO. HI and LO must not be changed by subsequent
2265663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng *  code emitted by the caller. */
2266663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
2267663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic void iselInt64Expr(HReg * rHi, HReg * rLo, ISelEnv * env, IRExpr * e)
2268663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
2269663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vassert(!env->mode64);
2270663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   iselInt64Expr_wrk(rHi, rLo, env, e);
2271663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vassert(hregClass(*rHi) == HRcInt32);
2272663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vassert(hregIsVirtual(*rHi));
2273663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vassert(hregClass(*rLo) == HRcInt32);
2274663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vassert(hregIsVirtual(*rLo));
2275663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
2276663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
2277663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* DO NOT CALL THIS DIRECTLY ! */
2278663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic void iselInt64Expr_wrk(HReg * rHi, HReg * rLo, ISelEnv * env, IRExpr * e)
2279663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
2280663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vassert(e);
2281663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vassert(typeOfIRExpr(env->type_env, e) == Ity_I64);
2282663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
2283663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* read 64-bit IRTemp */
2284663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (e->tag == Iex_RdTmp) {
2285663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      lookupIRTemp64(rHi, rLo, env, e->Iex.RdTmp.tmp);
2286663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      return;
2287663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
2288663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* 64-bit load */
2289663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (e->tag == Iex_Load) {
2290663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      HReg tLo = newVRegI(env);
2291663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      HReg tHi = newVRegI(env);
2292663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      HReg r_addr = iselWordExpr_R(env, e->Iex.Load.addr);
2293663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      addInstr(env, MIPSInstr_Load(4, tHi, MIPSAMode_IR(0, r_addr), mode64));
2294663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      addInstr(env, MIPSInstr_Load(4, tLo, MIPSAMode_IR(4, r_addr), mode64));
2295663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      *rHi = tHi;
2296663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      *rLo = tLo;
2297663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      return;
2298663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
2299663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
2300663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* 64-bit literal */
2301663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (e->tag == Iex_Const) {
2302663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      ULong w64 = e->Iex.Const.con->Ico.U64;
2303663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      UInt wHi = toUInt(w64 >> 32);
2304663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      UInt wLo = toUInt(w64);
2305663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      HReg tLo = newVRegI(env);
2306663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      HReg tHi = newVRegI(env);
2307663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      vassert(e->Iex.Const.con->tag == Ico_U64);
2308663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
2309663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (wLo == wHi) {
2310663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* Save a precious Int register in this special case. */
2311663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         addInstr(env, MIPSInstr_LI(tLo, (ULong) wLo));
2312663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         *rHi = tLo;
2313663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         *rLo = tLo;
2314663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      } else {
2315663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         addInstr(env, MIPSInstr_LI(tHi, (ULong) wHi));
2316663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         addInstr(env, MIPSInstr_LI(tLo, (ULong) wLo));
2317663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         *rHi = tHi;
2318663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         *rLo = tLo;
2319663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
2320663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
2321663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      return;
2322663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
2323663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
2324663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* 64-bit GET */
2325663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (e->tag == Iex_Get) {
2326663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      HReg tLo = newVRegI(env);
2327663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      HReg tHi = newVRegI(env);
2328663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
2329663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      MIPSAMode *am_addr = MIPSAMode_IR(e->Iex.Get.offset,
2330663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                        GuestStatePointer(mode64));
2331663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      addInstr(env, MIPSInstr_Load(4, tLo, am_addr, mode64));
2332663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      addInstr(env, MIPSInstr_Load(4, tHi, nextMIPSAModeInt(am_addr), mode64));
2333663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      *rHi = tHi;
2334663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      *rLo = tLo;
2335663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      return;
2336663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
2337663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
2338436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   /* 64-bit ITE */
2339436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   if (e->tag == Iex_ITE) {
2340436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      vassert(typeOfIRExpr(env->type_env, e->Iex.ITE.cond) == Ity_I1);
2341663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      HReg expr0Lo, expr0Hi;
2342436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      HReg expr1Lo, expr1Hi;
2343436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      HReg desLo  = newVRegI(env);
2344436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      HReg desHi  = newVRegI(env);
2345436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      HReg cond = iselWordExpr_R(env, e->Iex.ITE.cond);
2346436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
2347436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      /* expr0Hi:expr0Lo = iffalse */
2348436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      /* expr1Hi:expr1Lo = iftrue */
2349436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      iselInt64Expr(&expr0Hi, &expr0Lo, env, e->Iex.ITE.iffalse);
2350436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      iselInt64Expr(&expr1Hi, &expr1Lo, env, e->Iex.ITE.iftrue);
2351436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
2352436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      /* move desLo, expr0Lo
2353436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov       * move desHi, expr0Hi
2354436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov       * movn desLo, expr1Lo, cond
2355436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov       * movn desHi, expr1Hi, cond */
2356436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      addInstr(env, mk_iMOVds_RR(desLo, expr0Lo));
2357436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      addInstr(env, mk_iMOVds_RR(desHi, expr0Hi));
2358436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      addInstr(env, MIPSInstr_MoveCond(MMoveCond_movn, desLo, expr1Lo, cond));
2359436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      addInstr(env, MIPSInstr_MoveCond(MMoveCond_movn, desHi, expr1Hi, cond));
2360436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
2361663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      *rHi = desHi;
2362663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      *rLo = desLo;
2363663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      return;
2364663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
2365663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
2366663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* --------- BINARY ops --------- */
2367663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (e->tag == Iex_Binop) {
2368663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      IROp op_binop = e->Iex.Binop.op;
2369663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      switch (op_binop) {
2370663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* 32 x 32 -> 64 multiply */
2371663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* Add64 */
2372663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case Iop_Add64: {
2373436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            HReg xLo, xHi, yLo, yHi, carryBit;
2374436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
2375663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            HReg tHi = newVRegI(env);
2376436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            HReg tHi1 = newVRegI(env);
2377663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            HReg tLo = newVRegI(env);
2378436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
2379436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            carryBit = newVRegI(env);
2380436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
2381436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            Bool size32 = True;
2382436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            MIPSCondCode cc = MIPScc_LO;
2383436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
2384663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            iselInt64Expr(&xHi, &xLo, env, e->Iex.Binop.arg1);
2385663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            iselInt64Expr(&yHi, &yLo, env, e->Iex.Binop.arg2);
2386663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addInstr(env, MIPSInstr_Alu(Malu_ADD, tLo, xLo, MIPSRH_Reg(yLo)));
2387436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
2388436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            /* Check carry. */
2389436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            addInstr(env, MIPSInstr_Cmp(False, size32, carryBit, tLo, xLo, cc));
2390436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
2391436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            addInstr(env, MIPSInstr_Alu(Malu_ADD, tHi1, xHi, MIPSRH_Reg(yHi)));
2392436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            addInstr(env, MIPSInstr_Alu(Malu_ADD, tHi, tHi1,
2393436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                        MIPSRH_Reg(carryBit)));
2394436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
2395436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            *rHi = tHi;
2396436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            *rLo = tLo;
2397436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            return;
2398436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         }
2399436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         case Iop_Sub64: {
2400436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            HReg xLo, xHi, yLo, yHi, borrow;
2401436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            Bool size32 = True;
2402436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            MIPSCondCode cc = MIPScc_LO;
2403436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
2404436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            HReg tHi = newVRegI(env);
2405436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            HReg tLo = newVRegI(env);
2406436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
2407436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            borrow = newVRegI(env);
2408436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
2409436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            iselInt64Expr(&xHi, &xLo, env, e->Iex.Binop.arg1);
2410436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            iselInt64Expr(&yHi, &yLo, env, e->Iex.Binop.arg2);
2411436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
2412436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            addInstr(env, MIPSInstr_Alu(Malu_SUB, tLo, xLo, MIPSRH_Reg(yLo)));
2413436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
2414436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            /* Check if borrow is nedded. */
2415436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            addInstr(env, MIPSInstr_Cmp(False, size32, borrow, xLo, yLo, cc));
2416436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
2417436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            addInstr(env, MIPSInstr_Alu(Malu_ADD, yHi, yHi,
2418436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                        MIPSRH_Reg(borrow)));
2419436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            addInstr(env, MIPSInstr_Alu(Malu_SUB, tHi, xHi, MIPSRH_Reg(yHi)));
2420436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
2421663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            *rHi = tHi;
2422663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            *rLo = tLo;
2423663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            return;
2424663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
2425663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case Iop_MullU32:
2426663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case Iop_MullS32: {
2427663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            HReg tLo = newVRegI(env);
2428663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            HReg tHi = newVRegI(env);
2429663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            HReg r_dst = newVRegI(env);
2430663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            Bool syned = toBool(op_binop == Iop_MullS32);
2431663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            HReg r_srcL = iselWordExpr_R(env, e->Iex.Binop.arg1);
2432663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            HReg r_srcR = iselWordExpr_R(env, e->Iex.Binop.arg2);
2433663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
2434436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            addInstr(env, MIPSInstr_Mul(syned /*Unsigned or Signed */,
2435663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                        True /*widen */ , True,
2436663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                        r_dst, r_srcL, r_srcR));
2437663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addInstr(env, MIPSInstr_Mfhi(tHi));
2438663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addInstr(env, MIPSInstr_Mflo(tLo));
2439663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            *rHi = tHi;
2440663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            *rLo = tLo;
2441663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
2442663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            return;
2443663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
2444663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case Iop_DivModS64to32:
2445663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case Iop_DivModU64to32: {
2446663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            HReg r_sHi, r_sLo;
2447663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            HReg tLo = newVRegI(env);
2448663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            HReg tHi = newVRegI(env);
2449663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            Bool syned = toBool(op_binop == Iop_DivModS64to32);
2450663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            HReg r_srcR = iselWordExpr_R(env, e->Iex.Binop.arg2);
2451663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
2452663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            iselInt64Expr(&r_sHi, &r_sLo, env, e->Iex.Binop.arg1);
2453663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addInstr(env, MIPSInstr_Div(syned, True, r_sLo, r_srcR));
2454663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addInstr(env, MIPSInstr_Mfhi(tHi));
2455663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addInstr(env, MIPSInstr_Mflo(tLo));
2456663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            *rHi = tHi;
2457663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            *rLo = tLo;
2458663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
2459663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            return;
2460663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
2461663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
2462436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         /* 32HLto64(e1,e2) */
2463663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case Iop_32HLto64:
2464663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            *rHi = iselWordExpr_R(env, e->Iex.Binop.arg1);
2465663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            *rLo = iselWordExpr_R(env, e->Iex.Binop.arg2);
2466663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
2467663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            return;
2468436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         /* Or64/And64/Xor64 */
2469663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case Iop_Or64:
2470663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case Iop_And64:
2471663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case Iop_Xor64: {
2472663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            HReg xLo, xHi, yLo, yHi;
2473663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            HReg tLo = newVRegI(env);
2474663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            HReg tHi = newVRegI(env);
2475663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            MIPSAluOp op = (op_binop == Iop_Or64) ? Malu_OR :
2476663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                           (op_binop == Iop_And64) ? Malu_AND : Malu_XOR;
2477663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            iselInt64Expr(&xHi, &xLo, env, e->Iex.Binop.arg1);
2478663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            iselInt64Expr(&yHi, &yLo, env, e->Iex.Binop.arg2);
2479663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addInstr(env, MIPSInstr_Alu(op, tHi, xHi, MIPSRH_Reg(yHi)));
2480663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addInstr(env, MIPSInstr_Alu(op, tLo, xLo, MIPSRH_Reg(yLo)));
2481663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            *rHi = tHi;
2482663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            *rLo = tLo;
2483663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            return;
2484663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
2485663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
2486436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         case Iop_Shr64: {
2487436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#if defined (_MIPSEL)
2488436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            /* 64-bit logical shift right based on what gcc generates:
2489436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               <shift>:
2490436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               nor  v0, zero, a2
2491436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               sll  a3, a1, 0x1
2492436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               sllv a3, a3, v0
2493436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               srlv v0, a0, a2
2494436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               srlv v1, a1, a2
2495436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               andi a0, a2, 0x20
2496436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               or   v0, a3, v0
2497436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               movn v0, v1, a0
2498436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               jr   ra
2499436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               movn v1, zero, a0
2500436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            */
2501436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            HReg a0, a1;
2502436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            HReg a0tmp = newVRegI(env);
2503436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            HReg a2 = newVRegI(env);
2504436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            HReg a3 = newVRegI(env);
2505436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            HReg v0 = newVRegI(env);
2506436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            HReg v1 = newVRegI(env);
2507436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            HReg zero = newVRegI(env);
2508436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            MIPSRH *sa = NULL;
2509436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
2510436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            iselInt64Expr(&a1, &a0, env, e->Iex.Binop.arg1);
2511436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            sa = iselWordExpr_RH6u(env, e->Iex.Binop.arg2);
2512436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
2513436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            if (sa->tag == Mrh_Imm) {
2514436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               addInstr(env, MIPSInstr_LI(a2, sa->Mrh.Imm.imm16));
2515436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            }
2516436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            else {
2517436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               addInstr(env, MIPSInstr_Alu(Malu_AND, a2, sa->Mrh.Reg.reg,
2518436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                           MIPSRH_Imm(False, 0x3f)));
2519436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            }
2520436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
2521436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            addInstr(env, MIPSInstr_LI(zero, 0x00000000));
2522436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            /* nor  v0, zero, a2 */
2523436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            addInstr(env, MIPSInstr_Alu(Malu_NOR, v0, zero, MIPSRH_Reg(a2)));
2524436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            /* sll  a3, a1, 0x1 */
2525436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            addInstr(env, MIPSInstr_Shft(Mshft_SLL, True /* 32bit shift */,
2526436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                         a3, a1, MIPSRH_Imm(False, 0x1)));
2527436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            /* sllv a3, a3, v0 */
2528436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            addInstr(env, MIPSInstr_Shft(Mshft_SLL, True /* 32bit shift */,
2529436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                         a3, a3, MIPSRH_Reg(v0)));
2530436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            /* srlv v0, a0, a2 */
2531436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            addInstr(env, MIPSInstr_Shft(Mshft_SRL, True /* 32bit shift */,
2532436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                         v0, a0, MIPSRH_Reg(a2)));
2533436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            /* srlv v1, a1, a2 */
2534436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            addInstr(env, MIPSInstr_Shft(Mshft_SRL, True /* 32bit shift */,
2535436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                         v1, a1, MIPSRH_Reg(a2)));
2536436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            /* andi a0, a2, 0x20 */
2537436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            addInstr(env, MIPSInstr_Alu(Malu_AND, a0tmp, a2,
2538436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                        MIPSRH_Imm(False, 0x20)));
2539436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            /* or   v0, a3, v0 */
2540436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            addInstr(env, MIPSInstr_Alu(Malu_OR, v0, a3, MIPSRH_Reg(v0)));
2541436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
2542436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            /* movn    v0, v1, a0 */
2543436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            addInstr(env, MIPSInstr_MoveCond(MMoveCond_movn, v0, v1, a0tmp));
2544436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            /* movn    v1, zero, a0 */
2545436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            addInstr(env, MIPSInstr_MoveCond(MMoveCond_movn, v1, zero, a0tmp));
2546436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
2547436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            *rHi = v1;
2548436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            *rLo = v0;
2549436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            return;
2550436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#elif defined (_MIPSEB)
2551436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            /* 64-bit logical shift right based on what gcc generates:
2552436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               <shift>:
2553436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               nor  v0, zero, a2
2554436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               sll  a3, a0, 0x1
2555436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               sllv a3, a3, v0
2556436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               srlv v1, a1, a2
2557436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               andi v0, a2, 0x20
2558436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               or   v1, a3, v1
2559436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               srlv a2, a0, a2
2560436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               movn v1, a2, v0
2561436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               movn a2, zero, v0
2562436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               jr   ra
2563436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               move v0, a2
2564436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            */
2565436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            HReg a0, a1;
2566436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            HReg a2 = newVRegI(env);
2567436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            HReg a2tmp = newVRegI(env);
2568436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            HReg a3 = newVRegI(env);
2569436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            HReg v0 = newVRegI(env);
2570436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            HReg v1 = newVRegI(env);
2571436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            HReg zero = newVRegI(env);
2572436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            MIPSRH *sa = NULL;
2573436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
2574436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            iselInt64Expr(&a0, &a1, env, e->Iex.Binop.arg1);
2575436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            sa = iselWordExpr_RH6u(env, e->Iex.Binop.arg2);
2576436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
2577436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            if (sa->tag == Mrh_Imm) {
2578436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               addInstr(env, MIPSInstr_LI(a2, sa->Mrh.Imm.imm16));
2579436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            }
2580436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            else {
2581436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               addInstr(env, MIPSInstr_Alu(Malu_AND, a2, sa->Mrh.Reg.reg,
2582436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                           MIPSRH_Imm(False, 0x3f)));
2583436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            }
2584436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
2585436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            addInstr(env, MIPSInstr_LI(zero, 0x00000000));
2586436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            /* nor v0, zero, a2 */
2587436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            addInstr(env, MIPSInstr_Alu(Malu_NOR, v0, zero, MIPSRH_Reg(a2)));
2588436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            /* sll a3, a0, 0x1 */
2589436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            addInstr(env, MIPSInstr_Shft(Mshft_SLL, True /* 32bit shift */,
2590436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                         a3, a0, MIPSRH_Imm(False, 0x1)));
2591436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            /* sllv a3, a3, v0 */
2592436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            addInstr(env, MIPSInstr_Shft(Mshft_SLL, True /* 32bit shift */,
2593436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                         a3, a3, MIPSRH_Reg(v0)));
2594436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            /* srlv v1, a1, a2 */
2595436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            addInstr(env, MIPSInstr_Shft(Mshft_SRL, True /* 32bit shift */,
2596436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                         v1, a1, MIPSRH_Reg(a2)));
2597436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            /* andi v0, a2, 0x20 */
2598436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            addInstr(env, MIPSInstr_Alu(Malu_AND, v0, a2,
2599436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                        MIPSRH_Imm(False, 0x20)));
2600436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            /* or v1, a3, v1 */
2601436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            addInstr(env, MIPSInstr_Alu(Malu_OR, v1, a3, MIPSRH_Reg(v1)));
2602436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            /* srlv a2, a0, a2 */
2603436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            addInstr(env, MIPSInstr_Shft(Mshft_SRL, True /* 32bit shift */,
2604436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                             a2tmp, a0, MIPSRH_Reg(a2)));
2605436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
2606436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            /* movn v1, a2, v0 */
2607436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            addInstr(env, MIPSInstr_MoveCond(MMoveCond_movn, v1, a2tmp, v0));
2608436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            /* movn  a2, zero, v0 */
2609436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            addInstr(env, MIPSInstr_MoveCond(MMoveCond_movn, a2tmp, zero, v0));
2610436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            /* move v0, a2 */
2611436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            addInstr(env, mk_iMOVds_RR(v0, a2tmp));
2612436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
2613436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            *rHi = v0;
2614436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            *rLo = v1;
2615436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            return;
2616436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#endif
2617436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         }
2618436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
2619436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         case Iop_Shl64: {
2620436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            /* 64-bit shift left based on what gcc generates:
2621436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               <shift>:
2622436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               nor  v0,zero,a2
2623436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               srl  a3,a0,0x1
2624436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               srlv a3,a3,v0
2625436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               sllv v1,a1,a2
2626436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               andi v0,a2,0x20
2627436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               or   v1,a3,v1
2628436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               sllv a2,a0,a2
2629436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               movn v1,a2,v0
2630436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               movn a2,zero,v0
2631436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               jr   ra
2632436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               move v0,a2
2633436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            */
2634436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            HReg a0, a1;
2635436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            HReg a2 = newVRegI(env);
2636436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            HReg a3 = newVRegI(env);
2637436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            HReg v0 = newVRegI(env);
2638436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            HReg v1 = newVRegI(env);
2639436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            HReg zero = newVRegI(env);
2640436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            MIPSRH *sa = NULL;
2641436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
2642436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            iselInt64Expr(&a1, &a0, env, e->Iex.Binop.arg1);
2643436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            sa = iselWordExpr_RH6u(env, e->Iex.Binop.arg2);
2644436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
2645436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            if (sa->tag == Mrh_Imm) {
2646436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               addInstr(env, MIPSInstr_LI(a2, sa->Mrh.Imm.imm16));
2647436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            }
2648436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            else {
2649436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               addInstr(env, MIPSInstr_Alu(Malu_AND, a2, sa->Mrh.Reg.reg,
2650436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                           MIPSRH_Imm(False, 0x3f)));
2651436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            }
2652436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
2653436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            addInstr(env, MIPSInstr_LI(zero, 0x00000000));
2654436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            /* nor v0, zero, a2 */
2655436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            addInstr(env, MIPSInstr_Alu(Malu_NOR, v0, zero, MIPSRH_Reg(a2)));
2656436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            /* srl a3, a0, 0x1 */
2657436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            addInstr(env, MIPSInstr_Shft(Mshft_SRL, True /* 32bit shift */,
2658436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                         a3, a0, MIPSRH_Imm(False, 0x1)));
2659436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            /* srlv a3, a3, v0 */
2660436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            addInstr(env, MIPSInstr_Shft(Mshft_SRL, True /* 32bit shift */,
2661436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                         a3, a3, MIPSRH_Reg(v0)));
2662436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            /* sllv v1, a1, a2 */
2663436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            addInstr(env, MIPSInstr_Shft(Mshft_SLL, True /* 32bit shift */,
2664436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                         v1, a1, MIPSRH_Reg(a2)));
2665436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            /* andi v0, a2, 0x20 */
2666436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            addInstr(env, MIPSInstr_Alu(Malu_AND, v0, a2,
2667436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                        MIPSRH_Imm(False, 0x20)));
2668436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            /* or v1, a3, v1 */
2669436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            addInstr(env, MIPSInstr_Alu(Malu_OR, v1, a3, MIPSRH_Reg(v1)));
2670436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            /* sllv a2, a0, a2 */
2671436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            addInstr(env, MIPSInstr_Shft(Mshft_SLL, True /* 32bit shift */,
2672436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                         a2, a0, MIPSRH_Reg(a2)));
2673436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
2674436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            /* movn v1, a2, v0 */
2675436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            addInstr(env, MIPSInstr_MoveCond(MMoveCond_movn, v1, a2, v0));
2676436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            /* movn a2, zero, v0 */
2677436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            addInstr(env, MIPSInstr_MoveCond(MMoveCond_movn, a2, zero, v0));
2678436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            addInstr(env, mk_iMOVds_RR(v0, a2));
2679436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
2680436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            *rHi = v1;
2681436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            *rLo = v0;
2682436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            return;
2683436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         }
2684436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
2685436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         case Iop_Sar64: {
2686436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            /* 64-bit arithmetic shift right based on what gcc generates:
2687436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               <shift>:
2688436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               nor  v0, zero, a2
2689436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               sll  a3, a1, 0x1
2690436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               sllv a3, a3, v0
2691436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               srlv v0, a0, a2
2692436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               srav v1, a1, a2
2693436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               andi a0, a2, 0x20
2694436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               sra  a1, a1, 0x1f
2695436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               or   v0, a3, v0
2696436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               movn v0, v1, a0
2697436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               jr   ra
2698436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               movn v1, a1, a0
2699436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            */
2700436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            HReg a0, a1;
2701436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            HReg a0tmp = newVRegI(env);
2702436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            HReg a1tmp = newVRegI(env);
2703436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            HReg a2 = newVRegI(env);
2704436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            HReg a3 = newVRegI(env);
2705436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            HReg v0 = newVRegI(env);
2706436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            HReg v1 = newVRegI(env);
2707436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            HReg zero = newVRegI(env);
2708436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            MIPSRH *sa = NULL;
2709436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
2710436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            iselInt64Expr(&a1, &a0, env, e->Iex.Binop.arg1);
2711436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            sa = iselWordExpr_RH6u(env, e->Iex.Binop.arg2);
2712436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
2713436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            if (sa->tag == Mrh_Imm) {
2714436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               addInstr(env, MIPSInstr_LI(a2, sa->Mrh.Imm.imm16));
2715436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            }
2716436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            else {
2717436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               addInstr(env, MIPSInstr_Alu(Malu_AND, a2, sa->Mrh.Reg.reg,
2718436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                           MIPSRH_Imm(False, 0x3f)));
2719436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            }
2720436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
2721436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            addInstr(env, MIPSInstr_LI(zero, 0x00000000));
2722436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            /* nor  v0, zero, a2 */
2723436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            addInstr(env, MIPSInstr_Alu(Malu_NOR, v0, zero, MIPSRH_Reg(a2)));
2724436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            /* sll  a3, a1, 0x1 */
2725436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            addInstr(env, MIPSInstr_Shft(Mshft_SLL, True /* 32bit shift */,
2726436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                         a3, a1, MIPSRH_Imm(False, 0x1)));
2727436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            /* sllv a3, a3, v0 */
2728436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            addInstr(env, MIPSInstr_Shft(Mshft_SLL, True /* 32bit shift */,
2729436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                         a3, a3, MIPSRH_Reg(v0)));
2730436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            /* srlv v0, a0, a2 */
2731436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            addInstr(env, MIPSInstr_Shft(Mshft_SRL, True /* 32bit shift */,
2732436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                         v0, a0, MIPSRH_Reg(a2)));
2733436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            /* srav v1, a1, a2 */
2734436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            addInstr(env, MIPSInstr_Shft(Mshft_SRA, True /* 32bit shift */,
2735436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                         v1, a1, MIPSRH_Reg(a2)));
2736436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            /* andi a0, a2, 0x20 */
2737436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            addInstr(env, MIPSInstr_Alu(Malu_AND, a0tmp, a2,
2738436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                        MIPSRH_Imm(False, 0x20)));
2739436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            /* sra a1, a1, 0x1f */
2740436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            addInstr(env, MIPSInstr_Shft(Mshft_SRA, True /* 32bit shift */,
2741436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                         a1tmp, a1, MIPSRH_Imm(False, 0x1f)));
2742436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            /* or   v0, a3, v0 */
2743436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            addInstr(env, MIPSInstr_Alu(Malu_OR, v0, a3, MIPSRH_Reg(v0)));
2744436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
2745436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            /* movn    v0, v1, a0 */
2746436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            addInstr(env, MIPSInstr_MoveCond(MMoveCond_movn, v0, v1, a0tmp));
2747436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            /* movn    v1, a1, a0 */
2748436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            addInstr(env, MIPSInstr_MoveCond(MMoveCond_movn, v1, a1tmp, a0tmp));
2749436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
2750436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            *rHi = v1;
2751436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            *rLo = v0;
2752436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            return;
2753436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         }
2754436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
2755436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         case Iop_F32toI64S: {
2756436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            HReg tmpD = newVRegD(env);
2757436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            HReg valF = iselFltExpr(env, e->Iex.Binop.arg2);
2758436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            HReg tLo  = newVRegI(env);
2759436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            HReg tHi  = newVRegI(env);
2760436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            MIPSAMode *am_addr;
2761436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
2762436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            /* CVTLS tmpD, valF */
2763436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            set_MIPS_rounding_mode(env, e->Iex.Binop.arg1);
2764436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            addInstr(env, MIPSInstr_FpConvert(Mfp_CVTLS, tmpD, valF));
2765436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            set_MIPS_rounding_default(env);
2766436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
2767436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            sub_from_sp(env, 16);  /* Move SP down 16 bytes */
2768436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            am_addr = MIPSAMode_IR(0, StackPointer(mode64));
2769436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
2770436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            /* store as F64 */
2771436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            addInstr(env, MIPSInstr_FpLdSt(False /*store */ , 8, tmpD,
2772436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                           am_addr));
2773436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            /* load as 2xI32 */
2774436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#if defined (_MIPSEL)
2775436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            addInstr(env, MIPSInstr_Load(4, tLo, am_addr, mode64));
2776436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            addInstr(env, MIPSInstr_Load(4, tHi, nextMIPSAModeFloat(am_addr),
2777436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                         mode64));
2778436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#elif defined (_MIPSEB)
2779436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            addInstr(env, MIPSInstr_Load(4, tHi, am_addr, mode64));
2780436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            addInstr(env, MIPSInstr_Load(4, tLo, nextMIPSAModeFloat(am_addr),
2781436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                         mode64));
2782436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#endif
2783436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
2784436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            /* Reset SP */
2785436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            add_to_sp(env, 16);
2786436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
2787436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            *rHi = tHi;
2788436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            *rLo = tLo;
2789436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
2790436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            return;
2791436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         }
2792436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
2793663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         default:
2794663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            break;
2795663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
2796663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
2797663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
2798663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* --------- UNARY ops --------- */
2799663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (e->tag == Iex_Unop) {
2800663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      switch (e->Iex.Unop.op) {
2801663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case Iop_1Sto64: {
2802663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            HReg tLo = newVRegI(env);
2803663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            HReg tHi = newVRegI(env);
2804663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            HReg src = iselWordExpr_R(env, e->Iex.Unop.arg);
2805663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            HReg tmp = newVRegI(env);
2806663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
2807663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addInstr(env, MIPSInstr_Shft(Mshft_SLL, True, tmp, src,
2808663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                          MIPSRH_Imm(False, 31)));
2809436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            addInstr(env, MIPSInstr_Shft(Mshft_SRA, True, tmp, tmp,
2810663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                          MIPSRH_Imm(False, 31)));
2811663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
2812663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addInstr(env, mk_iMOVds_RR(tHi, tmp));
2813663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addInstr(env, mk_iMOVds_RR(tLo, tmp));
2814663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
2815663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            *rHi = tHi;
2816663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            *rLo = tLo;
2817663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            return;
2818663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
2819663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
2820663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* 32Sto64(e) */
2821663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case Iop_32Sto64: {
2822663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            HReg tLo = newVRegI(env);
2823663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            HReg tHi = newVRegI(env);
2824663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            HReg src = iselWordExpr_R(env, e->Iex.Unop.arg);
2825663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addInstr(env, mk_iMOVds_RR(tHi, src));
2826663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addInstr(env, mk_iMOVds_RR(tLo, src));
2827663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addInstr(env, MIPSInstr_Shft(Mshft_SRA, True, tHi, tHi,
2828663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                          MIPSRH_Imm(False, 31)));
2829663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            *rHi = tHi;
2830663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            *rLo = tLo;
2831663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            return;
2832663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
2833663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
2834436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         /* 8Uto64(e) */
2835436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         case Iop_8Uto64: {
2836436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            HReg tLo = newVRegI(env);
2837436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            HReg tHi = newVRegI(env);
2838436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            HReg src = iselWordExpr_R(env, e->Iex.Unop.arg);
2839436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            addInstr(env, MIPSInstr_Alu(Malu_AND, tLo, src,
2840436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                        MIPSRH_Imm(False, 0xFF)));
2841436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            addInstr(env, MIPSInstr_Alu(Malu_ADD, tHi, hregMIPS_GPR0(mode64),
2842436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                        MIPSRH_Reg(hregMIPS_GPR0(mode64))));
2843436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            *rHi = tHi;
2844436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            *rLo = tLo;
2845436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            return;
2846436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         }
2847436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
2848663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* 32Uto64(e) */
2849663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case Iop_32Uto64: {
2850663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            HReg tLo = newVRegI(env);
2851663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            HReg tHi = newVRegI(env);
2852663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            HReg src = iselWordExpr_R(env, e->Iex.Unop.arg);
2853663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addInstr(env, mk_iMOVds_RR(tLo, src));
2854663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addInstr(env, MIPSInstr_Alu(Malu_ADD, tHi, hregMIPS_GPR0(mode64),
2855663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                          MIPSRH_Reg(hregMIPS_GPR0(mode64))));
2856663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            *rHi = tHi;
2857663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            *rLo = tLo;
2858663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            return;
2859663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
2860436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
2861436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         case Iop_Left64: {
2862436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            HReg yHi, yLo;
2863436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            HReg tHi  = newVRegI(env);
2864436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            HReg tLo  = newVRegI(env);
2865436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            HReg tmp  = newVRegI(env);
2866436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            HReg tmp1  = newVRegI(env);
2867436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            HReg tmp2  = newVRegI(env);
2868436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            HReg zero = newVRegI(env);
2869436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            MIPSCondCode cc = MIPScc_LO;
2870436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
2871436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            /* yHi:yLo = arg */
2872436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            iselInt64Expr(&yHi, &yLo, env, e->Iex.Unop.arg);
2873436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            /* zero = 0 */
2874436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            addInstr(env, MIPSInstr_LI(zero, 0x00000000));
2875436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
2876436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            /* tmp2:tmp1 = 0 - (yHi:yLo)*/
2877436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            addInstr(env, MIPSInstr_Alu(Malu_SUB, tmp2, zero, MIPSRH_Reg(yLo)));
2878436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            addInstr(env, MIPSInstr_Cmp(False, True, tmp1, zero, tmp2, cc));
2879436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            addInstr(env, MIPSInstr_Alu(Malu_SUB, tmp, zero, MIPSRH_Reg(yHi)));
2880436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            addInstr(env, MIPSInstr_Alu(Malu_SUB, tmp1, tmp, MIPSRH_Reg(tmp1)));
2881436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
2882436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            /* So now we have tmp2:tmp1 = -arg.  To finish off, or 'arg'
2883436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               back in, so as to give the final result
2884436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               tHi:tLo = arg | -arg. */
2885436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            addInstr(env, MIPSInstr_Alu(Malu_OR, tHi, yHi, MIPSRH_Reg(tmp1)));
2886436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            addInstr(env, MIPSInstr_Alu(Malu_OR, tLo, yLo, MIPSRH_Reg(tmp2)));
2887436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            *rHi = tHi;
2888436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            *rLo = tLo;
2889436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            return;
2890436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         }
2891436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
2892663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case Iop_CmpwNEZ64: {
2893663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            HReg srcLo, srcHi;
2894663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            HReg tmp1 = newVRegI(env);
2895663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            HReg tmp2 = newVRegI(env);
2896663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            /* srcHi:srcLo = arg */
2897663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            iselInt64Expr(&srcHi, &srcLo, env, e->Iex.Unop.arg);
2898663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            /* tmp1 = srcHi | srcLo */
2899663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addInstr(env, MIPSInstr_Alu(Malu_OR, tmp1, srcLo,
2900663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                        MIPSRH_Reg(srcHi)));
2901663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            /* tmp2 = (tmp1 | -tmp1) >>s 31 */
2902663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
2903663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addInstr(env, MIPSInstr_Alu(Malu_SUB, tmp2, hregMIPS_GPR0(mode64),
2904663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                        MIPSRH_Reg(tmp1)));
2905663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
2906663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addInstr(env, MIPSInstr_Alu(Malu_OR, tmp2, tmp2, MIPSRH_Reg(tmp1)));
2907663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addInstr(env, MIPSInstr_Shft(Mshft_SRA, True, tmp2, tmp2,
2908663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                          MIPSRH_Imm(False, 31)));
2909663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            *rHi = tmp2;
2910663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            *rLo = tmp2;
2911663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            return;
2912663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
2913663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
2914663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case Iop_ReinterpF64asI64: {
2915663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            HReg tLo = newVRegI(env);
2916663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            HReg tHi = newVRegI(env);
2917663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            MIPSAMode *am_addr;
2918663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            HReg fr_src = iselDblExpr(env, e->Iex.Unop.arg);
2919663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
2920436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            sub_from_sp(env, 16);  /* Move SP down 16 bytes */
2921663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            am_addr = MIPSAMode_IR(0, StackPointer(mode64));
2922663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
2923436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            /* store as F64 */
2924663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addInstr(env, MIPSInstr_FpLdSt(False /*store */ , 8, fr_src,
2925663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                           am_addr));
2926436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            /* load as 2xI32 */
2927436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#if defined (_MIPSEL)
2928663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addInstr(env, MIPSInstr_Load(4, tLo, am_addr, mode64));
2929663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addInstr(env, MIPSInstr_Load(4, tHi, nextMIPSAModeFloat(am_addr),
2930663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                         mode64));
2931436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#elif defined (_MIPSEB)
2932436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            addInstr(env, MIPSInstr_Load(4, tHi, am_addr, mode64));
2933436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            addInstr(env, MIPSInstr_Load(4, tLo, nextMIPSAModeFloat(am_addr),
2934436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                         mode64));
2935436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#endif
2936663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
2937436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            /* Reset SP */
2938436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            add_to_sp(env, 16);
2939663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
2940663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            *rHi = tHi;
2941663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            *rLo = tLo;
2942663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            return;
2943663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
2944436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
2945663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         default:
2946663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            vex_printf("UNARY: No such op: ");
2947663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            ppIROp(e->Iex.Unop.op);
2948663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            vex_printf("\n");
2949663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            break;
2950663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
2951663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
2952663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
2953663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vex_printf("iselInt64Expr(mips): No such tag(%u)\n", e->tag);
2954663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   ppIRExpr(e);
2955663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vpanic("iselInt64Expr(mips)");
2956663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
2957663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
2958663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/*---------------------------------------------------------*/
2959663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/*--- ISEL: Floating point expressions (32 bit)         ---*/
2960663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/*---------------------------------------------------------*/
2961663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
2962663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* Nothing interesting here; really just wrappers for
2963663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   64-bit stuff. */
2964663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic HReg iselFltExpr(ISelEnv * env, IRExpr * e)
2965663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
2966663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   HReg r = iselFltExpr_wrk(env, e);
2967663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vassert(hregIsVirtual(r));
2968663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return r;
2969663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
2970663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
2971663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* DO NOT CALL THIS DIRECTLY */
2972663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic HReg iselFltExpr_wrk(ISelEnv * env, IRExpr * e)
2973663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
2974663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRType ty = typeOfIRExpr(env->type_env, e);
2975436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   vassert(ty == Ity_F32 || (ty == Ity_F64 && fp_mode64));
2976663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
2977663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (e->tag == Iex_RdTmp) {
2978663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      return lookupIRTemp(env, e->Iex.RdTmp.tmp);
2979663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
2980663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
2981663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (e->tag == Iex_Load) {
2982663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      vassert(e->Iex.Load.ty == Ity_F32
2983436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov              || (e->Iex.Load.ty == Ity_F64 && fp_mode64));
2984436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      HReg r_dst;
2985436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      MIPSAMode *am_addr = iselWordExpr_AMode(env, e->Iex.Load.addr, ty);
2986436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      if (e->Iex.Load.ty == Ity_F64) {
2987436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         r_dst = newVRegD(env);
2988436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         addInstr(env, MIPSInstr_FpLdSt(True /*load */, 8, r_dst, am_addr));
2989436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      } else {
2990436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         r_dst = newVRegF(env);
2991436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         addInstr(env, MIPSInstr_FpLdSt(True /*load */, 4, r_dst, am_addr));
2992436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      }
2993663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      return r_dst;
2994663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
2995663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
2996663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (e->tag == Iex_Get) {
2997663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      MIPSAMode *am_addr = MIPSAMode_IR(e->Iex.Get.offset,
2998663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                        GuestStatePointer(mode64));
2999436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      HReg r_dst;
3000436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      if (e->Iex.Load.ty == Ity_F64) {
3001436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         r_dst = newVRegD(env);
3002436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         addInstr(env, MIPSInstr_FpLdSt(True /*load */, 8, r_dst, am_addr));
3003436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      } else {
3004436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         r_dst = newVRegF(env);
3005436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         addInstr(env, MIPSInstr_FpLdSt(True /*load */, 4, r_dst, am_addr));
3006436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      }
3007663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      return r_dst;
3008663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
3009663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3010663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (e->tag == Iex_Unop) {
3011663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      switch (e->Iex.Unop.op) {
3012663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Iop_ReinterpI32asF32: {
3013663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         HReg fr_src = iselWordExpr_R(env, e->Iex.Unop.arg);
3014663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         HReg r_dst = newVRegF(env);
3015663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3016436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         /* Move Word to Floating Point
3017436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            mtc1 r_dst, valS */
3018436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         addInstr(env, MIPSInstr_FpGpMove(MFpGpMove_mtc1, r_dst, fr_src));
3019663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3020663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         return r_dst;
3021663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
3022663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Iop_F32toF64: {
3023436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         vassert(fp_mode64);
3024663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         HReg src = iselFltExpr(env, e->Iex.Unop.arg);
3025436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         HReg dst = newVRegD(env);
3026663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3027436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         addInstr(env, MIPSInstr_FpConvert(Mfp_CVTDS, dst, src));
3028663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         return dst;
3029663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
3030436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Iop_ReinterpI64asF64: {
3031436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         HReg r_dst;
3032436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         if (mode64) {
3033663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            HReg fr_src = iselWordExpr_R(env, e->Iex.Unop.arg);
3034436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            r_dst = newVRegF(env);
3035436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            /* Move Doubleword to Floating Point
3036436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               dmtc1 r_dst, fr_src */
3037436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            addInstr(env, MIPSInstr_FpGpMove(MFpGpMove_dmtc1, r_dst, fr_src));
3038436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         } else {
3039436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov             HReg Hi, Lo;
3040436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov             r_dst = newVRegD(env);
3041436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov             iselInt64Expr(&Hi, &Lo, env, e->Iex.Unop.arg);
3042436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov             r_dst = mk_LoadRR32toFPR(env, Hi, Lo);  /* 2*I32 -> F64 */
3043436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         }
3044436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         return r_dst;
3045436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      }
3046436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Iop_I32StoF64: {
3047436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         vassert(fp_mode64);
3048436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         HReg dst = newVRegF(env);
3049436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         HReg tmp = newVRegF(env);
3050436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         HReg r_src = iselWordExpr_R(env, e->Iex.Unop.arg);
3051663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3052436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         /* Move Word to Floating Point
3053436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            mtc1 tmp, r_src */
3054436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         addInstr(env, MIPSInstr_FpGpMove(MFpGpMove_mtc1, tmp, r_src));
3055663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3056436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         /* and do convert */
3057436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         addInstr(env, MIPSInstr_FpConvert(Mfp_CVTDW, dst, tmp));
3058663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3059436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         return dst;
3060436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      }
3061663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Iop_AbsF32:
3062663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Iop_AbsF64: {
3063663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         Bool sz32 = e->Iex.Unop.op == Iop_AbsF32;
3064663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         HReg src = iselFltExpr(env, e->Iex.Unop.arg);
3065663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         HReg dst = newVRegF(env);
3066663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         addInstr(env, MIPSInstr_FpUnary(sz32 ? Mfp_ABSS : Mfp_ABSD, dst, src));
3067663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         return dst;
3068663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
3069663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Iop_NegF32:
3070663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Iop_NegF64: {
3071663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         Bool sz32 = e->Iex.Unop.op == Iop_NegF32;
3072663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         HReg src = iselFltExpr(env, e->Iex.Unop.arg);
3073663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         HReg dst = newVRegF(env);
3074663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         addInstr(env, MIPSInstr_FpUnary(sz32 ? Mfp_NEGS : Mfp_NEGD, dst, src));
3075663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         return dst;
3076663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
3077436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Iop_RoundF64toF64_ZERO: {
3078436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         vassert(mode64);
3079436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         HReg src = iselFltExpr(env, e->Iex.Unop.arg);
3080436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         HReg dst = newVRegF(env);
3081436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         addInstr(env, MIPSInstr_FpConvert(Mfp_TRULD, dst, src));
3082436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         return dst;
3083436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      }
3084436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Iop_RoundF64toF64_NEAREST: {
3085436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         vassert(mode64);
3086436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         HReg src = iselFltExpr(env, e->Iex.Unop.arg);
3087436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         HReg dst = newVRegF(env);
3088436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         addInstr(env, MIPSInstr_FpConvert(Mfp_ROUNDLD, dst, src));
3089436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         return dst;
3090436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      }
3091436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Iop_RoundF64toF64_NegINF: {
3092436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         vassert(mode64);
3093436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         HReg src = iselFltExpr(env, e->Iex.Unop.arg);
3094436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         HReg dst = newVRegF(env);
3095436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         addInstr(env, MIPSInstr_FpConvert(Mfp_FLOORLD, dst, src));
3096436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         return dst;
3097436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      }
3098436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Iop_RoundF64toF64_PosINF: {
3099436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         vassert(mode64);
3100436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         HReg src = iselFltExpr(env, e->Iex.Unop.arg);
3101436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         HReg dst = newVRegF(env);
3102436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         addInstr(env, MIPSInstr_FpConvert(Mfp_CEILLD, dst, src));
3103436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         return dst;
3104436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      }
3105436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
3106663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      default:
3107663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         break;
3108663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
3109663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
3110663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3111663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (e->tag == Iex_Triop) {
3112663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      switch (e->Iex.Triop.details->op) {
3113663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case Iop_DivF32:
3114663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case Iop_DivF64:
3115663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case Iop_MulF32:
3116663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case Iop_MulF64:
3117663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case Iop_AddF32:
3118663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case Iop_AddF64:
3119663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case Iop_SubF32:
3120663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case Iop_SubF64: {
3121663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            MIPSFpOp op = 0;
3122436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            HReg argL = iselFltExpr(env, e->Iex.Triop.details->arg2);
3123663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            HReg argR = iselFltExpr(env, e->Iex.Triop.details->arg3);
3124663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            HReg dst = newVRegF(env);
3125663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            switch (e->Iex.Triop.details->op) {
3126663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               case Iop_DivF32:
3127663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  op = Mfp_DIVS;
3128663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  break;
3129436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               case Iop_DivF64:
3130436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                  vassert(fp_mode64);
3131436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                  op = Mfp_DIVD;
3132436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                  break;
3133663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               case Iop_MulF32:
3134663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  op = Mfp_MULS;
3135663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  break;
3136436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               case Iop_MulF64:
3137436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                  vassert(fp_mode64);
3138436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                  op = Mfp_MULD;
3139436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                  break;
3140663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               case Iop_AddF32:
3141663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  op = Mfp_ADDS;
3142663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  break;
3143436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               case Iop_AddF64:
3144436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                  vassert(fp_mode64);
3145436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                  op = Mfp_ADDD;
3146436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                  break;
3147663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               case Iop_SubF32:
3148663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  op = Mfp_SUBS;
3149663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  break;
3150436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               case Iop_SubF64:
3151436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                  vassert(fp_mode64);
3152436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                  op = Mfp_SUBD;
3153436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                  break;
3154663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               default:
3155663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  vassert(0);
3156663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            }
3157436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            set_MIPS_rounding_mode(env, e->Iex.Triop.details->arg1);
3158663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addInstr(env, MIPSInstr_FpBinary(op, dst, argL, argR));
3159436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            set_MIPS_rounding_default(env);
3160663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            return dst;
3161663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
3162663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         default:
3163663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            break;
3164663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
3165663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
3166663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3167663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (e->tag == Iex_Binop) {
3168663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      switch (e->Iex.Binop.op) {
3169663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case Iop_F64toF32: {
3170436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            HReg valD;
3171436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            if (mode64)
3172436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               valD = iselFltExpr(env, e->Iex.Binop.arg2);
3173436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            else
3174436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               valD = iselDblExpr(env, e->Iex.Binop.arg2);
3175663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            HReg valS = newVRegF(env);
3176663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3177663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            set_MIPS_rounding_mode(env, e->Iex.Binop.arg1);
3178663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addInstr(env, MIPSInstr_FpConvert(Mfp_CVTSD, valS, valD));
3179663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            set_MIPS_rounding_default(env);
3180663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            return valS;
3181663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
3182663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3183663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case Iop_RoundF32toInt: {
3184663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               HReg valS = newVRegF(env);
3185663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               HReg valF = iselFltExpr(env, e->Iex.Binop.arg2);
3186663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3187663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               set_MIPS_rounding_mode(env, e->Iex.Binop.arg1);
3188663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               addInstr(env, MIPSInstr_FpConvert(Mfp_CVTWS, valS, valF));
3189663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               set_MIPS_rounding_default(env);
3190663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               return valS;
3191663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            }
3192663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3193436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         case Iop_RoundF64toInt: {
3194436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            HReg valS = newVRegF(env);
3195436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            HReg valF = iselFltExpr(env, e->Iex.Binop.arg2);
3196436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
3197436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            set_MIPS_rounding_mode(env, e->Iex.Binop.arg1);
3198436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            addInstr(env, MIPSInstr_FpConvert(Mfp_CVTLD, valS, valF));
3199436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            set_MIPS_rounding_default(env);
3200436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            return valS;
3201436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         }
3202436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
3203663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case Iop_I32StoF32: {
3204663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            HReg r_dst = newVRegF(env);
3205663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            HReg fr_src = iselWordExpr_R(env, e->Iex.Binop.arg2);
3206663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            HReg tmp = newVRegF(env);
3207663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3208436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            /* Move Word to Floating Point
3209436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               mtc1 tmp, fr_src */
3210436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            addInstr(env, MIPSInstr_FpGpMove(MFpGpMove_mtc1, tmp, fr_src));
3211663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3212436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            set_MIPS_rounding_mode(env, e->Iex.Binop.arg1);
3213436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            addInstr(env, MIPSInstr_FpConvert(Mfp_CVTSW, r_dst, tmp));
3214436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            set_MIPS_rounding_default(env);
3215663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3216436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            return r_dst;
3217436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         }
3218663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3219436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         case Iop_I64StoF64: {
3220436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            HReg r_dst = newVRegF(env);
3221436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            MIPSAMode *am_addr;
3222436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            HReg tmp, fr_src;
3223436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            if (mode64) {
3224436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               tmp = newVRegF(env);
3225436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               fr_src = iselWordExpr_R(env, e->Iex.Binop.arg2);
3226436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               /* Move SP down 8 bytes */
3227436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               sub_from_sp(env, 8);
3228436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               am_addr = MIPSAMode_IR(0, StackPointer(mode64));
3229436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
3230436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               /* store as I64 */
3231436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               addInstr(env, MIPSInstr_Store(8, am_addr, fr_src, mode64));
3232436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
3233436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               /* load as Ity_F64 */
3234436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               addInstr(env, MIPSInstr_FpLdSt(True /*load */, 8, tmp, am_addr));
3235436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
3236436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               /* Reset SP */
3237436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               add_to_sp(env, 8);
3238436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            } else {
3239436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               HReg Hi, Lo;
3240436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               tmp = newVRegD(env);
3241436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               iselInt64Expr(&Hi, &Lo, env, e->Iex.Binop.arg2);
3242436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               tmp = mk_LoadRR32toFPR(env, Hi, Lo);  /* 2*I32 -> F64 */
3243436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            }
3244663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3245663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            set_MIPS_rounding_mode(env, e->Iex.Binop.arg1);
3246436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            addInstr(env, MIPSInstr_FpConvert(Mfp_CVTDL, r_dst, tmp));
3247436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            set_MIPS_rounding_default(env);
3248436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
3249436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            return r_dst;
3250436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         }
3251436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
3252436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         case Iop_I64StoF32: {
3253436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            HReg r_dst = newVRegF(env);
3254436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            MIPSAMode *am_addr;
3255436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            HReg fr_src, tmp;
3256436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            if (mode64) {
3257436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               tmp = newVRegF(env);
3258436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               fr_src = iselWordExpr_R(env, e->Iex.Binop.arg2);
3259436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               /* Move SP down 8 bytes */
3260436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               sub_from_sp(env, 8);
3261436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               am_addr = MIPSAMode_IR(0, StackPointer(mode64));
3262436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
3263436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               /* store as I64 */
3264436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               addInstr(env, MIPSInstr_Store(8, am_addr, fr_src, mode64));
3265436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
3266436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               /* load as Ity_F64 */
3267436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               addInstr(env, MIPSInstr_FpLdSt(True /*load */, 8, tmp, am_addr));
3268436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
3269436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               /* Reset SP */
3270436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               add_to_sp(env, 8);
3271436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            } else {
3272436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               HReg Hi, Lo;
3273436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               tmp = newVRegD(env);
3274436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               iselInt64Expr(&Hi, &Lo, env, e->Iex.Binop.arg2);
3275436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               tmp = mk_LoadRR32toFPR(env, Hi, Lo);  /* 2*I32 -> F64 */
3276436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            }
3277436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
3278436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            set_MIPS_rounding_mode(env, e->Iex.Binop.arg1);
3279436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            addInstr(env, MIPSInstr_FpConvert(Mfp_CVTSL, r_dst, tmp));
3280663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            set_MIPS_rounding_default(env);
3281663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3282663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            return r_dst;
3283663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
3284663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3285663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case Iop_SqrtF32:
3286663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case Iop_SqrtF64: {
3287663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            Bool sz32 = e->Iex.Binop.op == Iop_SqrtF32;
3288663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            HReg src = iselFltExpr(env, e->Iex.Binop.arg2);
3289663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            HReg dst = newVRegF(env);
3290663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            set_MIPS_rounding_mode(env, e->Iex.Binop.arg1);
3291663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addInstr(env, MIPSInstr_FpUnary(sz32 ? Mfp_SQRTS : Mfp_SQRTD, dst,
3292663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                            src));
3293663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            set_MIPS_rounding_default(env);
3294663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            return dst;
3295663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
3296436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
3297663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         default:
3298663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            break;
3299663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
3300663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
3301663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3302436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   if (e->tag == Iex_Qop) {
3303436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      switch (e->Iex.Qop.details->op) {
3304436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         case Iop_MAddF32:
3305436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         case Iop_MAddF64:
3306436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         case Iop_MSubF32:
3307436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         case Iop_MSubF64: {
3308436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            MIPSFpOp op = 0;
3309436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            switch (e->Iex.Qop.details->op) {
3310436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               case Iop_MAddF32:
3311436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                  op = Mfp_MADDS;
3312436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                  break;
3313436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               case Iop_MAddF64:
3314436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                  op = Mfp_MADDD;
3315436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                  break;
3316436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               case Iop_MSubF32:
3317436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                  op = Mfp_MSUBS;
3318436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                  break;
3319436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               case Iop_MSubF64:
3320436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                  op = Mfp_MSUBD;
3321436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                  break;
3322436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               default:
3323436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                  vassert(0);
3324436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            }
3325436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            HReg dst = newVRegF(env);
3326436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            HReg src1 = iselFltExpr(env, e->Iex.Qop.details->arg2);
3327436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            HReg src2 = iselFltExpr(env, e->Iex.Qop.details->arg3);
3328436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            HReg src3 = iselFltExpr(env, e->Iex.Qop.details->arg4);
3329436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            set_MIPS_rounding_mode(env, e->Iex.Qop.details->arg1);
3330436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            addInstr(env, MIPSInstr_FpTernary(op, dst,
3331436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                              src1, src2, src3));
3332436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            set_MIPS_rounding_default(env);
3333436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            return dst;
3334436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         }
3335436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
3336436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         default:
3337436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         break;
3338436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      }
3339436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   }
3340436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
3341663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (e->tag == Iex_Unop && e->Iex.Unop.op == Iop_TruncF64asF32) {
3342663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* This is quite subtle.  The only way to do the relevant
3343663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         truncation is to do a single-precision store and then a
3344663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         double precision load to get it back into a register.  The
3345663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         problem is, if the data is then written to memory a second
3346663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         time, as in
3347663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3348663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         STbe(...) = TruncF64asF32(...)
3349663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3350663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         then will the second truncation further alter the value?  The
3351663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         answer is no: flds (as generated here) followed by fsts
3352663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         (generated for the STbe) is the identity function on 32-bit
3353663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         floats, so we are safe.
3354663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3355663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         Another upshot of this is that if iselStmt can see the
3356663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         entirety of
3357663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3358663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         STbe(...) = TruncF64asF32(arg)
3359663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3360663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         then it can short circuit having to deal with TruncF64asF32
3361663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         individually; instead just compute arg into a 64-bit FP
3362663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         register and do 'fsts' (since that itself does the
3363663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         truncation).
3364663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3365663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         We generate pretty poor code here (should be ok both for
3366663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         32-bit and 64-bit mode); but it is expected that for the most
3367663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         part the latter optimisation will apply and hence this code
3368663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         will not often be used.
3369663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng       */
3370663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      HReg fsrc = iselDblExpr(env, e->Iex.Unop.arg);
3371663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      HReg fdst = newVRegF(env);
3372663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      MIPSAMode *zero_r1 = MIPSAMode_IR(0, StackPointer(mode64));
3373663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3374663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      sub_from_sp(env, 16);
3375436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      /* store as F32, hence truncating */
3376663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      addInstr(env, MIPSInstr_FpLdSt(False /*store */ , 4, fsrc, zero_r1));
3377436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      /* and reload.  Good huh?! (sigh) */
3378663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      addInstr(env, MIPSInstr_FpLdSt(True /*load */ , 4, fdst, zero_r1));
3379663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      add_to_sp(env, 16);
3380663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      return fdst;
3381663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
3382663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3383436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   /* --------- ITE --------- */
3384436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   if (e->tag == Iex_ITE) {
3385436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      if (ty == Ity_F64
3386436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov          && typeOfIRExpr(env->type_env, e->Iex.ITE.cond) == Ity_I1) {
3387436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         vassert(mode64);
3388436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         HReg r0 = iselFltExpr(env, e->Iex.ITE.iffalse);
3389436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         HReg r1 = iselFltExpr(env, e->Iex.ITE.iftrue);
3390436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         HReg r_cond = iselWordExpr_R(env, e->Iex.ITE.cond);
3391436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         HReg r_dst = newVRegF(env);
3392436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         addInstr(env, MIPSInstr_FpUnary(Mfp_MOVD, r_dst, r0));
3393436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         addInstr(env, MIPSInstr_MoveCond(MFpMoveCond_movnd, r_dst, r1,
3394436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                            r_cond));
3395436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         return r_dst;
3396436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      }
3397436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   }
3398436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
3399663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vex_printf("iselFltExpr(mips): No such tag(0x%x)\n", e->tag);
3400663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   ppIRExpr(e);
3401663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vpanic("iselFltExpr_wrk(mips)");
3402663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
3403663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3404663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic HReg iselDblExpr(ISelEnv * env, IRExpr * e)
3405663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
3406663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   HReg r = iselDblExpr_wrk(env, e);
3407663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vassert(hregClass(r) == HRcFlt64);
3408663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vassert(hregIsVirtual(r));
3409663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return r;
3410663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
3411663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3412663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* DO NOT CALL THIS DIRECTLY */
3413663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic HReg iselDblExpr_wrk(ISelEnv * env, IRExpr * e)
3414663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
3415663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRType ty = typeOfIRExpr(env->type_env, e);
3416663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vassert(e);
3417663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vassert(ty == Ity_F64);
3418663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3419663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (e->tag == Iex_RdTmp) {
3420663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      return lookupIRTemp(env, e->Iex.RdTmp.tmp);
3421663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
3422663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3423663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* --------- LOAD --------- */
3424436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   if (e->tag == Iex_Load) {
3425663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      HReg r_dst = newVRegD(env);
3426663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      MIPSAMode *am_addr;
3427663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      vassert(e->Iex.Load.ty == Ity_F64);
3428663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      am_addr = iselWordExpr_AMode(env, e->Iex.Load.addr, ty);
3429663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      addInstr(env, MIPSInstr_FpLdSt(True /*load */ , 8, r_dst, am_addr));
3430663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      return r_dst;
3431663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
3432663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3433663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* --------- GET --------- */
3434663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (e->tag == Iex_Get) {
3435663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3436663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      HReg r_dst = newVRegD(env);
3437663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      MIPSAMode *am_addr = MIPSAMode_IR(e->Iex.Get.offset,
3438663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                        GuestStatePointer(mode64));
3439663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      addInstr(env, MIPSInstr_FpLdSt(True /*load */ , 8, r_dst, am_addr));
3440663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      return r_dst;
3441663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
3442663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3443663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (e->tag == Iex_Unop) {
3444663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      MIPSFpOp fpop = Mfp_INVALID;
3445663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      switch (e->Iex.Unop.op) {
3446663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case Iop_NegF64:
3447663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            fpop = Mfp_NEGD;
3448663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            break;
3449663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case Iop_AbsF64:
3450663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            fpop = Mfp_ABSD;
3451663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            break;
3452663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case Iop_F32toF64: {
3453436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            vassert(!mode64);
3454663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            HReg src = iselFltExpr(env, e->Iex.Unop.arg);
3455663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            HReg dst = newVRegD(env);
3456663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3457436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            addInstr(env, MIPSInstr_FpConvert(Mfp_CVTDS, dst, src));
3458663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            return dst;
3459663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
3460663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case Iop_ReinterpI64asF64: {
3461436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            HReg Hi, Lo;
3462663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            HReg dst = newVRegD(env);
3463663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3464663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            iselInt64Expr(&Hi, &Lo, env, e->Iex.Unop.arg);
3465663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3466436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            dst = mk_LoadRR32toFPR(env, Hi, Lo);  /* 2*I32 -> F64 */
3467663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            return dst;
3468663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
3469663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case Iop_I32StoF64: {
3470436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            vassert(!mode64);
3471663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            HReg dst = newVRegD(env);
3472436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            HReg tmp = newVRegF(env);
3473663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            HReg r_src = iselWordExpr_R(env, e->Iex.Unop.arg);
3474663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3475436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            /* Move Word to Floating Point
3476436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               mtc1 tmp, r_src */
3477436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            addInstr(env, MIPSInstr_FpGpMove(MFpGpMove_mtc1, tmp, r_src));
3478663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3479436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            /* and do convert */
3480436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            addInstr(env, MIPSInstr_FpConvert(Mfp_CVTDW, dst, tmp));
3481663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3482663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            return dst;
3483663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
3484663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         default:
3485663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            break;
3486663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
3487663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3488663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (fpop != Mfp_INVALID) {
3489663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         HReg src = iselDblExpr(env, e->Iex.Unop.arg);
3490663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         HReg dst = newVRegD(env);
3491663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         addInstr(env, MIPSInstr_FpUnary(fpop, dst, src));
3492663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         return dst;
3493663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
3494663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
3495663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3496663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (e->tag == Iex_Binop) {
3497663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      switch (e->Iex.Binop.op) {
3498663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case Iop_RoundF64toInt: {
3499436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            HReg src = iselDblExpr(env, e->Iex.Binop.arg2);
3500436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            HReg dst = newVRegD(env);
3501436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
3502436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            set_MIPS_rounding_mode(env, e->Iex.Binop.arg1);
3503436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            addInstr(env, MIPSInstr_FpConvert(Mfp_CVTLD, dst, src));
3504436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            set_MIPS_rounding_default(env);
3505436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
3506436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            return dst;
3507663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
3508663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3509436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         case Iop_SqrtF64: {
3510663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            HReg src = iselDblExpr(env, e->Iex.Binop.arg2);
3511663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            HReg dst = newVRegD(env);
3512436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            set_MIPS_rounding_mode(env, e->Iex.Binop.arg1);
3513663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addInstr(env, MIPSInstr_FpUnary(Mfp_SQRTD, dst, src));
3514436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            set_MIPS_rounding_default(env);
3515663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            return dst;
3516663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
3517663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3518663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         default:
3519663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            break;
3520663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3521663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
3522663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
3523663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3524663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (e->tag == Iex_Triop) {
3525663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      switch (e->Iex.Triop.details->op) {
3526663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case Iop_DivF64:
3527663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case Iop_DivF32:
3528663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case Iop_MulF64:
3529663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case Iop_AddF64:
3530663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case Iop_SubF64: {
3531663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            MIPSFpOp op = 0;
3532436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            HReg argL = iselDblExpr(env, e->Iex.Triop.details->arg2);
3533663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            HReg argR = iselDblExpr(env, e->Iex.Triop.details->arg3);
3534663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            HReg dst = newVRegD(env);
3535663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            switch (e->Iex.Triop.details->op) {
3536663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               case Iop_DivF64:
3537663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  op = Mfp_DIVD;
3538663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  break;
3539436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               case Iop_DivF32:
3540436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                  op = Mfp_DIVS;
3541436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                  break;
3542663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               case Iop_MulF64:
3543663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  op = Mfp_MULD;
3544663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  break;
3545663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               case Iop_AddF64:
3546663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  op = Mfp_ADDD;
3547663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  break;
3548663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               case Iop_SubF64:
3549663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  op = Mfp_SUBD;
3550663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  break;
3551663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               default:
3552663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  vassert(0);
3553663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            }
3554436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            set_MIPS_rounding_mode(env, e->Iex.Triop.details->arg1);
3555663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addInstr(env, MIPSInstr_FpBinary(op, dst, argL, argR));
3556436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            set_MIPS_rounding_default(env);
3557663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            return dst;
3558663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
3559663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         default:
3560663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            break;
3561663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
3562663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
3563663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3564436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   if (e->tag == Iex_Qop) {
3565436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      switch (e->Iex.Qop.details->op) {
3566436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         case Iop_MAddF32:
3567436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         case Iop_MAddF64:
3568436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         case Iop_MSubF32:
3569436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         case Iop_MSubF64: {
3570436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            MIPSFpOp op = 0;
3571436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            switch (e->Iex.Qop.details->op) {
3572436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               case Iop_MAddF32:
3573436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                  op = Mfp_MADDS;
3574436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                  break;
3575436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               case Iop_MAddF64:
3576436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                  op = Mfp_MADDD;
3577436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                  break;
3578436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               case Iop_MSubF32:
3579436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                  op = Mfp_MSUBS;
3580436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                  break;
3581436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               case Iop_MSubF64:
3582436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                  op = Mfp_MSUBD;
3583436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                  break;
3584436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               default:
3585436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                  vassert(0);
3586436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            }
3587436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            HReg dst = newVRegD(env);
3588436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            HReg src1 = iselDblExpr(env, e->Iex.Qop.details->arg2);
3589436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            HReg src2 = iselDblExpr(env, e->Iex.Qop.details->arg3);
3590436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            HReg src3 = iselDblExpr(env, e->Iex.Qop.details->arg4);
3591436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            set_MIPS_rounding_mode(env, e->Iex.Qop.details->arg1);
3592436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            addInstr(env, MIPSInstr_FpTernary(op, dst,
3593436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                              src1, src2, src3));
3594436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            set_MIPS_rounding_default(env);
3595436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            return dst;
3596436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         }
3597663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3598436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         default:
3599436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         break;
3600436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      }
3601436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   }
3602663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3603436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   /* --------- ITE --------- */
3604436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   if (e->tag == Iex_ITE) {
3605436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      if (ty == Ity_F64
3606436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov          && typeOfIRExpr(env->type_env, e->Iex.ITE.cond) == Ity_I1) {
3607436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         HReg r0 = iselDblExpr(env, e->Iex.ITE.iffalse);
3608436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         HReg r1 = iselDblExpr(env, e->Iex.ITE.iftrue);
3609436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         HReg r_cond = iselWordExpr_R(env, e->Iex.ITE.cond);
3610436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         HReg r_dst = newVRegD(env);
3611663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3612436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         addInstr(env, MIPSInstr_FpUnary(Mfp_MOVD, r_dst, r0));
3613436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         addInstr(env, MIPSInstr_MoveCond(MFpMoveCond_movnd, r_dst, r1,
3614436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                            r_cond));
3615663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         return r_dst;
3616663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
3617663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
3618663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3619663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vex_printf("iselDblExpr(mips): No such tag(%u)\n", e->tag);
3620663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   ppIRExpr(e);
3621663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vpanic("iselDblExpr_wrk(mips)");
3622663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
3623663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3624663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/*---------------------------------------------------------*/
3625663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/*--- ISEL: Statements                                  ---*/
3626663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/*---------------------------------------------------------*/
3627663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3628663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic void iselStmt(ISelEnv * env, IRStmt * stmt)
3629663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
3630663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (vex_traceflags & VEX_TRACE_VCODE) {
3631663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      vex_printf("\n-- ");
3632663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3633663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      ppIRStmt(stmt);
3634663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      vex_printf("\n");
3635663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
3636663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3637663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   switch (stmt->tag) {
3638663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* --------- STORE --------- */
3639663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Ist_Store: {
3640663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         MIPSAMode *am_addr;
3641663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRType tyd = typeOfIRExpr(env->type_env, stmt->Ist.Store.data);
3642663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3643663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /*constructs addressing mode from address provided */
3644663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         am_addr = iselWordExpr_AMode(env, stmt->Ist.Store.addr, tyd);
3645663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3646663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (tyd == Ity_I8 || tyd == Ity_I16 || tyd == Ity_I32 ||
3647663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng             (mode64 && (tyd == Ity_I64))) {
3648663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            HReg r_src = iselWordExpr_R(env, stmt->Ist.Store.data);
3649663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addInstr(env, MIPSInstr_Store(toUChar(sizeofIRType(tyd)),
3650663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                     am_addr, r_src, mode64));
3651663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            return;
3652663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
3653663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (!mode64 && (tyd == Ity_I64)) {
3654663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            HReg vHi, vLo;
3655663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            HReg r_addr = iselWordExpr_R(env, stmt->Ist.Store.addr);
3656663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3657663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            iselInt64Expr(&vHi, &vLo, env, stmt->Ist.Store.data);
3658663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3659663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addInstr(env, MIPSInstr_Store(toUChar(sizeofIRType(Ity_I32)),
3660663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                          MIPSAMode_IR(0, r_addr), vHi, mode64));
3661663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addInstr(env, MIPSInstr_Store(toUChar(sizeofIRType(Ity_I32)),
3662663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                          MIPSAMode_IR(4, r_addr), vLo, mode64));
3663663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            return;
3664663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
3665663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (tyd == Ity_F32) {
3666663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            HReg fr_src = iselFltExpr(env, stmt->Ist.Store.data);
3667663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addInstr(env, MIPSInstr_FpLdSt(False /*store */ , 4, fr_src,
3668663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                           am_addr));
3669663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            return;
3670663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
3671436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         if (tyd == Ity_F64 && mode64) {
3672436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            HReg fr_src = iselFltExpr(env, stmt->Ist.Store.data);
3673436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            addInstr(env, MIPSInstr_FpLdSt(False /*store */ , 8, fr_src,
3674436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                           am_addr));
3675436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            return;
3676436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         }
3677436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         if (!mode64 && (tyd == Ity_F64)) {
3678436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            HReg fr_src = iselDblExpr(env, stmt->Ist.Store.data);
3679436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            addInstr(env, MIPSInstr_FpLdSt(False /*store */ , 8, fr_src,
3680436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                           am_addr));
3681436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            return;
3682436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         }
3683663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3684663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         break;
3685663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
3686663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3687663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* --------- PUT --------- */
3688663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Ist_Put: {
3689663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRType ty = typeOfIRExpr(env->type_env, stmt->Ist.Put.data);
3690436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
3691663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (ty == Ity_I8 || ty == Ity_I16 || ty == Ity_I32 ||
3692663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng             (ty == Ity_I64 && mode64)) {
3693663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            HReg r_src = iselWordExpr_R(env, stmt->Ist.Put.data);
3694663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            MIPSAMode *am_addr = MIPSAMode_IR(stmt->Ist.Put.offset,
3695663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                              GuestStatePointer(mode64));
3696663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addInstr(env, MIPSInstr_Store(toUChar(sizeofIRType(ty)),
3697663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                          am_addr, r_src, mode64));
3698663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            return;
3699663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
3700436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
3701663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (ty == Ity_I64 && !mode64) {
3702663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            HReg vHi, vLo;
3703663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            MIPSAMode *am_addr = MIPSAMode_IR(stmt->Ist.Put.offset,
3704663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                              GuestStatePointer(mode64));
3705663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            MIPSAMode *am_addr4 = MIPSAMode_IR(stmt->Ist.Put.offset + 4,
3706663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                               GuestStatePointer(mode64));
3707663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            iselInt64Expr(&vHi, &vLo, env, stmt->Ist.Put.data);
3708663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addInstr(env, MIPSInstr_Store(toUChar(sizeofIRType(Ity_I32)),
3709663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                          am_addr, vLo, mode64));
3710663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addInstr(env, MIPSInstr_Store(toUChar(sizeofIRType(Ity_I32)),
3711663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                          am_addr4, vHi, mode64));
3712663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            return;
3713436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
3714663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
3715436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
3716663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (ty == Ity_F32) {
3717663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            HReg fr_src = iselFltExpr(env, stmt->Ist.Put.data);
3718663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            MIPSAMode *am_addr = MIPSAMode_IR(stmt->Ist.Put.offset,
3719663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                              GuestStatePointer(mode64));
3720663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addInstr(env, MIPSInstr_FpLdSt(False /*store */ , 4, fr_src,
3721663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                           am_addr));
3722663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            return;
3723663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
3724436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
3725663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (ty == Ity_F64) {
3726436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            HReg fr_src = iselFltExpr(env, stmt->Ist.Put.data);
3727663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            MIPSAMode *am_addr = MIPSAMode_IR(stmt->Ist.Put.offset,
3728663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                              GuestStatePointer(mode64));
3729663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addInstr(env, MIPSInstr_FpLdSt(False /*store */ , 8, fr_src,
3730663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                           am_addr));
3731663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            return;
3732663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
3733663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         break;
3734663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
3735663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3736663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* --------- TMP --------- */
3737663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Ist_WrTmp: {
3738663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp tmp = stmt->Ist.WrTmp.tmp;
3739663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRType ty = typeOfIRTemp(env->type_env, tmp);
3740663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3741663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (ty == Ity_I8 || ty == Ity_I16 || ty == Ity_I32 || ty == Ity_I1) {
3742663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            HReg r_dst = lookupIRTemp(env, tmp);
3743663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            HReg r_src = iselWordExpr_R(env, stmt->Ist.WrTmp.data);
3744663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addInstr(env, mk_iMOVds_RR(r_dst, r_src));
3745663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            return;
3746663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
3747663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3748663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (ty == Ity_I64) {
3749436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            if (mode64) {
3750436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               HReg r_dst = lookupIRTemp(env, tmp);
3751436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               HReg r_src = iselWordExpr_R(env, stmt->Ist.WrTmp.data);
3752436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               addInstr(env, mk_iMOVds_RR(r_dst, r_src));
3753436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               return;
3754436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            } else {
3755436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               HReg rHi, rLo, dstHi, dstLo;
3756436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               iselInt64Expr(&rHi, &rLo, env, stmt->Ist.WrTmp.data);
3757436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               lookupIRTemp64(&dstHi, &dstLo, env, tmp);
3758436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               addInstr(env, mk_iMOVds_RR(dstHi, rHi));
3759436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               addInstr(env, mk_iMOVds_RR(dstLo, rLo));
3760436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               return;
3761436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            }
3762436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         }
3763436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
3764436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         if (mode64 && ty == Ity_I128) {
3765436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            HReg rHi, rLo, dstHi, dstLo;
3766436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            iselInt128Expr(&rHi, &rLo, env, stmt->Ist.WrTmp.data);
3767436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            lookupIRTempPair(&dstHi, &dstLo, env, tmp);
3768436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            addInstr(env, mk_iMOVds_RR(dstHi, rHi));
3769436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            addInstr(env, mk_iMOVds_RR(dstLo, rLo));
3770436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            return;
3771663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
3772663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3773663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (ty == Ity_F32) {
3774663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            HReg fr_dst = lookupIRTemp(env, tmp);
3775663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            HReg fr_src = iselFltExpr(env, stmt->Ist.WrTmp.data);
3776663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addInstr(env, MIPSInstr_FpUnary(Mfp_MOVS, fr_dst, fr_src));
3777663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            return;
3778663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
3779663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3780663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (ty == Ity_F64) {
3781436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            if (mode64) {
3782436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               HReg src = iselFltExpr(env, stmt->Ist.WrTmp.data);
3783436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               HReg dst = lookupIRTemp(env, tmp);
3784436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               addInstr(env, MIPSInstr_FpUnary(Mfp_MOVD, dst, src));
3785436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               return;
3786436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            } else {
3787436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               HReg src = iselDblExpr(env, stmt->Ist.WrTmp.data);
3788436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               HReg dst = lookupIRTemp(env, tmp);
3789436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               addInstr(env, MIPSInstr_FpUnary(Mfp_MOVD, dst, src));
3790436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               return;
3791436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            }
3792663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
3793663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         break;
3794663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
3795663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3796663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* --------- Call to DIRTY helper --------- */
3797663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Ist_Dirty: {
3798663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRDirty *d = stmt->Ist.Dirty.details;
3799663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3800436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         /* Figure out the return type, if any. */
3801436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         IRType retty = Ity_INVALID;
3802436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         if (d->tmp != IRTemp_INVALID)
3803436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            retty = typeOfIRTemp(env->type_env, d->tmp);
3804436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
3805436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         /* Throw out any return types we don't know about. */
3806436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         Bool retty_ok = False;
3807436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         switch (retty) {
3808436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            case Ity_INVALID: /* Function doesn't return anything. */
3809436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            case Ity_V128:
3810436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            case Ity_I64: case Ity_I32: case Ity_I16: case Ity_I8:
3811436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               retty_ok = True; break;
3812436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            default:
3813436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               break;
3814436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         }
3815436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
3816436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         if (!retty_ok)
3817436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            break; /* will go to stmt_fail: */
3818663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3819436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         /* Marshal args, do the call, clear stack, set the return value
3820436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            to 0x555..555 if this is a conditional call that returns a
3821436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            value and the call is skipped. */
3822436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         UInt   addToSp = 0;
3823436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         RetLoc rloc    = mk_RetLoc_INVALID();
3824436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         doHelperCall( &addToSp, &rloc, env, d->guard, d->cee, retty, d->args );
3825436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         vassert(is_sane_RetLoc(rloc));
3826663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3827663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* Now figure out what to do with the returned value, if any. */
3828436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         switch (retty) {
3829436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            case Ity_INVALID: {
3830436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               /* No return value.  Nothing to do. */
3831436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               vassert(d->tmp == IRTemp_INVALID);
3832436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               vassert(rloc.pri == RLPri_None);
3833436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               vassert(addToSp == 0);
3834436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               return;
3835436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            }
3836436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            case Ity_I32: case Ity_I16: case Ity_I8: {
3837436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               /* The returned value is in $v0.  Park it in the register
3838436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                  associated with tmp. */
3839436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               HReg r_dst = lookupIRTemp(env, d->tmp);
3840436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               addInstr(env, mk_iMOVds_RR(r_dst, hregMIPS_GPR2(mode64)));
3841436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               vassert(rloc.pri == RLPri_Int);
3842436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               vassert(addToSp == 0);
3843436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               return;
3844436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            }
3845436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            case Ity_I64: {
3846436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               if (mode64) {
3847436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                  /* The returned value is in $v0.  Park it in the register
3848436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                     associated with tmp. */
3849436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                  HReg r_dst = lookupIRTemp(env, d->tmp);
3850436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                  addInstr(env, mk_iMOVds_RR(r_dst, hregMIPS_GPR2(mode64)));
3851436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                  vassert(rloc.pri == RLPri_Int);
3852436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                  vassert(addToSp == 0);
3853436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                  return;
3854436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               } else {
3855436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                  HReg rHi = newVRegI(env);
3856436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                  HReg rLo = newVRegI(env);
3857436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                  HReg dstHi, dstLo;
3858436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                  addInstr(env, mk_iMOVds_RR(rLo, hregMIPS_GPR2(mode64)));
3859436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                  addInstr(env, mk_iMOVds_RR(rHi, hregMIPS_GPR3(mode64)));
3860436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                  lookupIRTemp64(&dstHi, &dstLo, env, d->tmp);
3861436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                  addInstr(env, mk_iMOVds_RR(dstHi, rHi));
3862436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                  addInstr(env, mk_iMOVds_RR(dstLo, rLo));
3863436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                  return;
3864436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               }
3865436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            }
3866436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            case Ity_V128: {
3867436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               /* ATC. The code that this produces really
3868436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                  needs to be looked at, to verify correctness.
3869436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                  I don't think this can ever happen though, since the
3870436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                  MIPS front end never produces 128-bit loads/stores. */
3871436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               vassert(0);
3872436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               vassert(rloc.pri == RLPri_V128SpRel);
3873436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               vassert(addToSp >= 16);
3874436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               HReg       dst = lookupIRTemp(env, d->tmp);
3875436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               MIPSAMode* am  = MIPSAMode_IR(rloc.spOff, StackPointer(mode64));
3876436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               addInstr(env, MIPSInstr_Load(mode64 ? 8 : 4, dst, am, mode64));
3877436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               add_to_sp(env, addToSp);
3878436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               return;
3879663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3880436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            }
3881436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            default:
3882436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               /*NOTREACHED*/
3883436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               vassert(0);
3884663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
3885663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
3886663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3887663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* --------- Load Linked or Store Conditional --------- */
3888663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Ist_LLSC: {
3889436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         /* Temporary solution; this need to be rewritten again for MIPS.
3890436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            On MIPS you can not read from address that is locked with LL
3891436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            before SC. If you read from address that is locked than SC will
3892436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            fall. */
3893663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp res = stmt->Ist.LLSC.result;
3894663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRType tyRes = typeOfIRTemp(env->type_env, res);
3895663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRType tyAddr = typeOfIRExpr(env->type_env, stmt->Ist.LLSC.addr);
3896663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3897663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (!mode64 && (tyAddr != Ity_I32))
3898663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            goto stmt_fail;
3899663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3900663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (stmt->Ist.LLSC.storedata == NULL) {
3901663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            /* LL */
3902663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            MIPSAMode *r_addr;
3903436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            /* constructs addressing mode from address provided */
3904663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            r_addr = iselWordExpr_AMode(env, stmt->Ist.LLSC.addr, tyAddr);
3905663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3906663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            HReg r_dst = lookupIRTemp(env, res);
3907663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            if (tyRes == Ity_I32) {
3908436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               addInstr(env, MIPSInstr_LoadL(4, r_dst, r_addr, mode64));
3909663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               return;
3910663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            } else if (tyRes == Ity_I64 && mode64) {
3911436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               addInstr(env, MIPSInstr_LoadL(8, r_dst, r_addr, mode64));
3912663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               return;
3913663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            }
3914663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         } else {
3915663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            /* SC */
3916663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            MIPSAMode *r_addr;
3917663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            r_addr = iselWordExpr_AMode(env, stmt->Ist.LLSC.addr, tyAddr);
3918663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            HReg r_src = iselWordExpr_R(env, stmt->Ist.LLSC.storedata);
3919663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            HReg r_dst = lookupIRTemp(env, res);
3920436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            IRType tyData = typeOfIRExpr(env->type_env,
3921663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                         stmt->Ist.LLSC.storedata);
3922663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3923663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            if (tyData == Ity_I32) {
3924436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               addInstr(env, mk_iMOVds_RR(r_dst, r_src));
3925436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               addInstr(env, MIPSInstr_StoreC(4, r_addr, r_dst, mode64));
3926663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               return;
3927663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            } else if (tyData == Ity_I64 && mode64) {
3928436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               addInstr(env, mk_iMOVds_RR(r_dst, r_src));
3929436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               addInstr(env, MIPSInstr_StoreC(8, r_addr, r_dst, mode64));
3930663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               return;
3931663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            }
3932663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
3933663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto stmt_fail;
3934436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov       /* NOTREACHED */}
3935663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3936436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   /* --------- INSTR MARK --------- */
3937436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   /* Doesn't generate any executable code ... */
3938663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case Ist_IMark:
3939663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      return;
3940663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3941436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   /* --------- ABI HINT --------- */
3942436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   /* These have no meaning (denotation in the IR) and so we ignore
3943436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      them ... if any actually made it this far. */
3944663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case Ist_AbiHint:
3945663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      return;
3946663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3947436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   /* --------- NO-OP --------- */
3948436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   /* Fairly self-explanatory, wouldn't you say? */
3949663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case Ist_NoOp:
3950663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      return;
3951663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3952663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* --------- EXIT --------- */
3953663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   case Ist_Exit: {
3954663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      IRConst* dst = stmt->Ist.Exit.dst;
3955663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (!mode64 && dst->tag != Ico_U32)
3956663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         vpanic("iselStmt(mips32): Ist_Exit: dst is not a 32-bit value");
3957663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (mode64 && dst->tag != Ico_U64)
3958663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         vpanic("iselStmt(mips64): Ist_Exit: dst is not a 64-bit value");
3959663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3960663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      MIPSCondCode cc   = iselCondCode(env, stmt->Ist.Exit.guard);
3961663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      MIPSAMode*   amPC = MIPSAMode_IR(stmt->Ist.Exit.offsIP,
3962436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                      GuestStatePointer(mode64));
3963663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3964663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* Case: boring transfer to known address */
3965663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (stmt->Ist.Exit.jk == Ijk_Boring
3966663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          || stmt->Ist.Exit.jk == Ijk_Call
3967663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          /* || stmt->Ist.Exit.jk == Ijk_Ret */) {
3968663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (env->chainingAllowed) {
3969663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            /* .. almost always true .. */
3970663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            /* Skip the event check at the dst if this is a forwards
3971663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               edge. */
3972663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            Bool toFastEP
3973663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               = mode64
3974663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               ? (((Addr64)stmt->Ist.Exit.dst->Ico.U64) > (Addr64)env->max_ga)
3975663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               : (((Addr32)stmt->Ist.Exit.dst->Ico.U32) > (Addr32)env->max_ga);
3976663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            if (0) vex_printf("%s", toFastEP ? "Y" : ",");
3977663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addInstr(env, MIPSInstr_XDirect(
3978663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                             mode64 ? (Addr64)stmt->Ist.Exit.dst->Ico.U64
3979663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                    : (Addr64)stmt->Ist.Exit.dst->Ico.U32,
3980663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                             amPC, cc, toFastEP));
3981663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         } else {
3982663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            /* .. very occasionally .. */
3983663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            /* We can't use chaining, so ask for an assisted transfer,
3984663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               as that's the only alternative that is allowable. */
3985663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            HReg r = iselWordExpr_R(env, IRExpr_Const(stmt->Ist.Exit.dst));
3986663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addInstr(env, MIPSInstr_XAssisted(r, amPC, cc, Ijk_Boring));
3987663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
3988663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         return;
3989663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
3990663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3991663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* Case: assisted transfer to arbitrary address */
3992663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      switch (stmt->Ist.Exit.jk) {
3993663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* Keep this list in sync with that in iselNext below */
3994663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case Ijk_ClientReq:
3995663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case Ijk_EmFail:
3996663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case Ijk_EmWarn:
3997663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case Ijk_NoDecode:
3998663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case Ijk_NoRedir:
3999663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case Ijk_SigBUS:
4000663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case Ijk_SigTRAP:
4001436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         case Ijk_SigFPE_IntDiv:
4002436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         case Ijk_SigFPE_IntOvf:
4003663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case Ijk_Sys_syscall:
4004eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov         case Ijk_InvalICache:
4005663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         {
4006663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            HReg r = iselWordExpr_R(env, IRExpr_Const(stmt->Ist.Exit.dst));
4007663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addInstr(env, MIPSInstr_XAssisted(r, amPC, cc,
4008663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                             stmt->Ist.Exit.jk));
4009663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            return;
4010663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
4011663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         default:
4012663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            break;
4013663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
4014663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
4015663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* Do we ever expect to see any other kind? */
4016663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      goto stmt_fail;
4017663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
4018663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
4019663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   default:
4020663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      break;
4021663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
4022663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
4023663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   stmt_fail:
4024663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      vex_printf("stmt_fail tag: 0x%x\n", stmt->tag);
4025663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      ppIRStmt(stmt);
4026663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      vpanic("iselStmt:\n");
4027663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
4028663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
4029663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/*---------------------------------------------------------*/
4030663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/*--- ISEL: Basic block terminators (Nexts)             ---*/
4031663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/*---------------------------------------------------------*/
4032663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
4033663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic void iselNext ( ISelEnv* env,
4034663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                       IRExpr* next, IRJumpKind jk, Int offsIP )
4035663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
4036663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (vex_traceflags & VEX_TRACE_VCODE) {
4037663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      vex_printf( "\n-- PUT(%d) = ", offsIP);
4038663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      ppIRExpr( next );
4039663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      vex_printf( "; exit-");
4040663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      ppIRJumpKind(jk);
4041663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      vex_printf( "\n");
4042663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
4043663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
4044663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* Case: boring transfer to known address */
4045663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (next->tag == Iex_Const) {
4046663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      IRConst* cdst = next->Iex.Const.con;
4047663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      vassert(cdst->tag == (env->mode64 ? Ico_U64 :Ico_U32));
4048663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (jk == Ijk_Boring || jk == Ijk_Call) {
4049663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* Boring transfer to known address */
4050436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         MIPSAMode* amPC = MIPSAMode_IR(offsIP, GuestStatePointer(env->mode64));
4051663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (env->chainingAllowed) {
4052663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            /* .. almost always true .. */
4053663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            /* Skip the event check at the dst if this is a forwards
4054663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               edge. */
4055663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            Bool toFastEP
4056663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               = env->mode64
4057663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               ? (((Addr64)cdst->Ico.U64) > (Addr64)env->max_ga)
4058663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               : (((Addr32)cdst->Ico.U32) > (Addr32)env->max_ga);
4059663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            if (0) vex_printf("%s", toFastEP ? "X" : ".");
4060663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addInstr(env, MIPSInstr_XDirect(
4061663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                             env->mode64 ? (Addr64)cdst->Ico.U64
4062663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                         : (Addr64)cdst->Ico.U32,
4063663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                             amPC, MIPScc_AL, toFastEP));
4064663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         } else {
4065663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            /* .. very occasionally .. */
4066663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            /* We can't use chaining, so ask for an assisted transfer,
4067663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               as that's the only alternative that is allowable. */
4068663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            HReg r = iselWordExpr_R(env, next);
4069663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addInstr(env, MIPSInstr_XAssisted(r, amPC, MIPScc_AL,
4070663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                              Ijk_Boring));
4071663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
4072663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         return;
4073663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
4074663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
4075663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
4076663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* Case: call/return (==boring) transfer to any address */
4077663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   switch (jk) {
4078663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Ijk_Boring: case Ijk_Ret: case Ijk_Call: {
4079663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         HReg       r     = iselWordExpr_R(env, next);
4080436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         MIPSAMode*  amPC = MIPSAMode_IR(offsIP,
4081436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                         GuestStatePointer(env->mode64));
4082663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (env->chainingAllowed) {
4083663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addInstr(env, MIPSInstr_XIndir(r, amPC, MIPScc_AL));
4084663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         } else {
4085663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addInstr(env, MIPSInstr_XAssisted(r, amPC, MIPScc_AL,
4086436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                              Ijk_Boring));
4087663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
4088663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         return;
4089663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
4090663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      default:
4091663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         break;
4092663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
4093663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
4094663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* Case: assisted transfer to arbitrary address */
4095663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   switch (jk) {
4096663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* Keep this list in sync with that for Ist_Exit above */
4097663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Ijk_ClientReq:
4098663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Ijk_EmFail:
4099663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Ijk_EmWarn:
4100663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Ijk_NoDecode:
4101663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Ijk_NoRedir:
4102663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Ijk_SigBUS:
4103436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Ijk_SigILL:
4104663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Ijk_SigTRAP:
4105436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Ijk_SigFPE_IntDiv:
4106436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Ijk_SigFPE_IntOvf:
4107663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Ijk_Sys_syscall:
4108eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov      case Ijk_InvalICache: {
4109663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         HReg      r     = iselWordExpr_R(env, next);
4110436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         MIPSAMode* amPC = MIPSAMode_IR(offsIP, GuestStatePointer(env->mode64));
4111663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         addInstr(env, MIPSInstr_XAssisted(r, amPC, MIPScc_AL, jk));
4112663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         return;
4113663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
4114663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      default:
4115663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         break;
4116663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
4117663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
4118436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   vex_printf("\n-- PUT(%d) = ", offsIP);
4119436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   ppIRExpr(next );
4120436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   vex_printf("; exit-");
4121663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   ppIRJumpKind(jk);
4122436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   vex_printf("\n");
4123436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   vassert(0);  /* are we expecting any other kind? */
4124663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
4125663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
4126663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/*---------------------------------------------------------*/
4127663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/*--- Insn selector top-level                           ---*/
4128663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/*---------------------------------------------------------*/
4129663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
4130663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* Translate an entire BB to mips code. */
4131663860b1408516d02ebfcb3a9999a134e6cfb223Ben ChengHInstrArray *iselSB_MIPS ( IRSB* bb,
4132663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                           VexArch arch_host,
4133663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                           VexArchInfo* archinfo_host,
4134663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                           VexAbiInfo* vbi,
4135663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                           Int offs_Host_EvC_Counter,
4136663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                           Int offs_Host_EvC_FailAddr,
4137663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                           Bool chainingAllowed,
4138663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                           Bool addProfInc,
4139663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                           Addr64 max_ga )
4140663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
4141663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   Int      i, j;
4142663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   HReg     hreg, hregHI;
4143663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   ISelEnv* env;
4144663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UInt     hwcaps_host = archinfo_host->hwcaps;
4145663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   MIPSAMode *amCounter, *amFailAddr;
4146663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
4147663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* sanity ... */
4148436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   vassert(arch_host == VexArchMIPS32 || arch_host == VexArchMIPS64);
4149663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vassert(VEX_PRID_COMP_MIPS == hwcaps_host
4150436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov           || VEX_PRID_COMP_BROADCOM == hwcaps_host
4151436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov           || VEX_PRID_COMP_NETLOGIC);
4152663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
4153663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   mode64 = arch_host != VexArchMIPS32;
4154436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#if (__mips_fpr==64)
4155436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   fp_mode64 = ((VEX_MIPS_REV(hwcaps_host) == VEX_PRID_CPU_32FPR)
4156436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                || arch_host == VexArchMIPS64);
4157436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#endif
4158663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
4159663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* Make up an initial environment to use. */
4160663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   env = LibVEX_Alloc(sizeof(ISelEnv));
4161663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   env->vreg_ctr = 0;
4162663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   env->mode64 = mode64;
4163436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   env->fp_mode64 = fp_mode64;
4164663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
4165663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* Set up output code array. */
4166663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   env->code = newHInstrArray();
4167663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
4168663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* Copy BB's type env. */
4169663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   env->type_env = bb->tyenv;
4170663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
4171663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* Make up an IRTemp -> virtual HReg mapping.  This doesn't
4172663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      change as we go along. */
4173663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   env->n_vregmap = bb->tyenv->types_used;
4174663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   env->vregmap = LibVEX_Alloc(env->n_vregmap * sizeof(HReg));
4175663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   env->vregmapHI = LibVEX_Alloc(env->n_vregmap * sizeof(HReg));
4176663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
4177663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* and finally ... */
4178663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   env->hwcaps          = hwcaps_host;
4179663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   env->chainingAllowed = chainingAllowed;
4180663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   env->hwcaps          = hwcaps_host;
4181663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   env->max_ga          = max_ga;
4182663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
4183663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* For each IR temporary, allocate a suitably-kinded virtual
4184663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      register. */
4185663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   j = 0;
4186663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   for (i = 0; i < env->n_vregmap; i++) {
4187663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      hregHI = hreg = INVALID_HREG;
4188663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      switch (bb->tyenv->types[i]) {
4189663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case Ity_I1:
4190663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case Ity_I8:
4191663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case Ity_I16:
4192436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         case Ity_I32:
4193436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            if (mode64) {
4194436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               hreg = mkHReg(j++, HRcInt64, True);
4195436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               break;
4196436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            } else {
4197436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               hreg = mkHReg(j++, HRcInt32, True);
4198436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               break;
4199436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            }
4200436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         case Ity_I64:
4201436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            if (mode64) {
4202436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               hreg = mkHReg(j++, HRcInt64, True);
4203436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               break;
4204436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            } else {
4205436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               hreg = mkHReg(j++, HRcInt32, True);
4206436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               hregHI = mkHReg(j++, HRcInt32, True);
4207436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               break;
4208436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            }
4209663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case Ity_I128:
4210663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            vassert(mode64);
4211663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            hreg = mkHReg(j++, HRcInt64, True);
4212663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            hregHI = mkHReg(j++, HRcInt64, True);
4213663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            break;
4214436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         case Ity_F32:
4215436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            if (mode64) {
4216436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               hreg = mkHReg(j++, HRcFlt64, True);
4217436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               break;
4218436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            } else {
4219436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               hreg = mkHReg(j++, HRcFlt32, True);
4220436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               break;
4221436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            }
4222663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case Ity_F64:
4223663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            hreg = mkHReg(j++, HRcFlt64, True);
4224663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            break;
4225663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         default:
4226663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            ppIRType(bb->tyenv->types[i]);
4227663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            vpanic("iselBB(mips): IRTemp type");
4228436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            break;
4229663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
4230663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      env->vregmap[i] = hreg;
4231663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      env->vregmapHI[i] = hregHI;
4232663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
4233663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   env->vreg_ctr = j;
4234663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
4235663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* The very first instruction must be an event check. */
4236436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   amCounter = MIPSAMode_IR(offs_Host_EvC_Counter, GuestStatePointer(mode64));
4237436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   amFailAddr = MIPSAMode_IR(offs_Host_EvC_FailAddr, GuestStatePointer(mode64));
4238663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   addInstr(env, MIPSInstr_EvCheck(amCounter, amFailAddr));
4239663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
4240663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* Possibly a block counter increment (for profiling).  At this
4241663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      point we don't know the address of the counter, so just pretend
4242663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      it is zero.  It will have to be patched later, but before this
4243663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      translation is used, by a call to LibVEX_patchProfCtr. */
4244663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (addProfInc) {
4245663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      addInstr(env, MIPSInstr_ProfInc());
4246663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
4247663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
4248663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* Ok, finally we can iterate over the statements. */
4249663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   for (i = 0; i < bb->stmts_used; i++)
4250663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      iselStmt(env, bb->stmts[i]);
4251663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
4252663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   iselNext(env, bb->next, bb->jumpkind, bb->offsIP);
4253663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
4254663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* record the number of vregs we used. */
4255663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   env->code->n_vregs = env->vreg_ctr;
4256663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return env->code;
4257663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
4258663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
4259663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
4260663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/*---------------------------------------------------------------*/
4261663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/*--- end                                    host_mips_isel.c ---*/
4262663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/*---------------------------------------------------------------*/
4263