blob: 7d14df253a914a7d62a8760190642f53867d5b92 [file] [log] [blame]
sewardjc97096c2004-06-30 09:28:04 +00001
2/*---------------------------------------------------------------*/
3/*--- ---*/
sewardjc0ee2ed2004-07-27 10:29:41 +00004/*--- This file (host-x86/isel.c) is ---*/
sewardjc97096c2004-06-30 09:28:04 +00005/*--- Copyright (c) 2004 OpenWorks LLP. All rights reserved. ---*/
6/*--- ---*/
7/*---------------------------------------------------------------*/
8
sewardjf8ed9d82004-11-12 17:40:23 +00009/*
10 This file is part of LibVEX, a library for dynamic binary
11 instrumentation and translation.
12
13 Copyright (C) 2004 OpenWorks, LLP.
14
15 This program is free software; you can redistribute it and/or modify
16 it under the terms of the GNU General Public License as published by
17 the Free Software Foundation; Version 2 dated June 1991 of the
18 license.
19
20 This program is distributed in the hope that it will be useful,
21 but WITHOUT ANY WARRANTY; without even the implied warranty of
22 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or liability
23 for damages. See the GNU General Public License for more details.
24
25 Neither the names of the U.S. Department of Energy nor the
26 University of California nor the names of its contributors may be
27 used to endorse or promote products derived from this software
28 without prior written permission.
29
30 You should have received a copy of the GNU General Public License
31 along with this program; if not, write to the Free Software
32 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
33 USA.
34*/
35
sewardj887a11a2004-07-05 17:26:47 +000036#include "libvex_basictypes.h"
37#include "libvex_ir.h"
38#include "libvex.h"
sewardj35421a32004-07-05 13:12:34 +000039
sewardjc0ee2ed2004-07-27 10:29:41 +000040#include "main/vex_util.h"
41#include "main/vex_globals.h"
42#include "host-generic/h_generic_regs.h"
43#include "host-x86/hdefs.h"
sewardjc97096c2004-06-30 09:28:04 +000044
45
46/*---------------------------------------------------------*/
sewardj443cd9d2004-07-18 23:06:45 +000047/*--- Stuff for pattern matching on IR. This isn't ---*/
48/*--- x86 specific, and should be moved elsewhere. ---*/
49/*---------------------------------------------------------*/
50
51#define DECLARE_PATTERN(_patt) \
52 static IRExpr* _patt = NULL
53
54#define DEFINE_PATTERN(_patt,_expr) \
55 do { \
56 if (!(_patt)) { \
57 vassert(LibVEX_GetAllocMode() == AllocModeTEMPORARY); \
58 LibVEX_SetAllocMode(AllocModePERMANENT); \
59 _patt = (_expr); \
60 LibVEX_SetAllocMode(AllocModeTEMPORARY); \
61 vassert(LibVEX_GetAllocMode() == AllocModeTEMPORARY); \
62 } \
63 } while (0)
64
65
66#define N_MATCH_BINDERS 4
67typedef
68 struct {
69 IRExpr* bindee[N_MATCH_BINDERS];
70 }
71 MatchInfo;
72
73
74static void setBindee ( MatchInfo* mi, Int n, IRExpr* bindee )
75{
76 if (n < 0 || n >= N_MATCH_BINDERS)
77 vpanic("setBindee: out of range index");
78 if (mi->bindee[n] != NULL)
79 vpanic("setBindee: bindee already set");
80 mi->bindee[n] = bindee;
81}
82
83static Bool matchWrk ( MatchInfo* mi, IRExpr* p/*attern*/, IRExpr* e/*xpr*/ )
84{
85 switch (p->tag) {
86 case Iex_Binder: /* aha, what we were looking for. */
87 setBindee(mi, p->Iex.Binder.binder, e);
88 return True;
sewardj2d3f77c2004-09-22 23:49:09 +000089#if 0
sewardj08790542004-09-14 23:18:06 +000090 case Iex_GetI:
91 if (e->tag != Iex_GetI) return False;
92 if (p->Iex.GetI.ty != e->Iex.GetI.ty) return False;
93 /* we ignore the offset limit hints .. */
94 if (!matchWrk(mi, p->Iex.GetI.offset, e->Iex.GetI.offset))
95 return False;
96 return True;
sewardj2d3f77c2004-09-22 23:49:09 +000097#endif
sewardj443cd9d2004-07-18 23:06:45 +000098 case Iex_Unop:
99 if (e->tag != Iex_Unop) return False;
100 if (p->Iex.Unop.op != e->Iex.Unop.op) return False;
101 if (!matchWrk(mi, p->Iex.Unop.arg, e->Iex.Unop.arg))
102 return False;
103 return True;
104 case Iex_Binop:
105 if (e->tag != Iex_Binop) return False;
106 if (p->Iex.Binop.op != e->Iex.Binop.op) return False;
107 if (!matchWrk(mi, p->Iex.Binop.arg1, e->Iex.Binop.arg1))
108 return False;
109 if (!matchWrk(mi, p->Iex.Binop.arg2, e->Iex.Binop.arg2))
110 return False;
111 return True;
sewardjd18d1bf2004-08-25 12:49:22 +0000112 case Iex_LDle:
113 if (e->tag != Iex_LDle) return False;
114 if (p->Iex.LDle.ty != e->Iex.LDle.ty) return False;
115 if (!matchWrk(mi, p->Iex.LDle.addr, e->Iex.LDle.addr))
116 return False;
117 return True;
sewardj443cd9d2004-07-18 23:06:45 +0000118 case Iex_Const:
sewardj4345f7a2004-09-22 19:49:27 +0000119 if (e->tag != Iex_Const) return False;
120 return eqIRConst(p->Iex.Const.con, e->Iex.Const.con);
sewardj443cd9d2004-07-18 23:06:45 +0000121 default:
122 ppIRExpr(p);
123 vpanic("match");
124 }
125}
126
127static Bool matchIRExpr ( MatchInfo* mi, IRExpr* p/*attern*/, IRExpr* e/*xpr*/ )
128{
129 Int i;
130 for (i = 0; i < N_MATCH_BINDERS; i++)
131 mi->bindee[i] = NULL;
132 return matchWrk(mi, p, e);
133}
134
135/*-----*/
136/* These are duplicated in x86toIR.c */
137static IRExpr* unop ( IROp op, IRExpr* a )
138{
139 return IRExpr_Unop(op, a);
140}
141
142static IRExpr* binop ( IROp op, IRExpr* a1, IRExpr* a2 )
143{
144 return IRExpr_Binop(op, a1, a2);
145}
sewardj08790542004-09-14 23:18:06 +0000146
sewardj6f33f752004-11-11 02:17:53 +0000147static IRExpr* mkU64 ( ULong i )
sewardj08790542004-09-14 23:18:06 +0000148{
sewardj6f33f752004-11-11 02:17:53 +0000149 return IRExpr_Const(IRConst_U64(i));
sewardj08790542004-09-14 23:18:06 +0000150}
sewardj6f33f752004-11-11 02:17:53 +0000151
152static IRExpr* mkU32 ( UInt i )
153{
154 return IRExpr_Const(IRConst_U32(i));
155}
sewardj443cd9d2004-07-18 23:06:45 +0000156
157static IRExpr* bind ( Int binder )
158{
159 return IRExpr_Binder(binder);
160}
161
162
163
164
165/*---------------------------------------------------------*/
sewardjc97096c2004-06-30 09:28:04 +0000166/*--- ISelEnv ---*/
167/*---------------------------------------------------------*/
168
169/* This carries around:
170
171 - A mapping from IRTemp to IRType, giving the type of any IRTemp we
172 might encounter. This is computed before insn selection starts,
173 and does not change.
174
175 - A mapping from IRTemp to HReg. This tells the insn selector
sewardje8e9d732004-07-16 21:03:45 +0000176 which virtual register(s) are associated with each IRTemp
177 temporary. This is computed before insn selection starts, and
178 does not change. We expect this mapping to map precisely the
179 same set of IRTemps as the type mapping does.
180
181 - vregmap holds the primary register for the IRTemp.
182 - vregmapHI is only used for 64-bit integer-typed
183 IRTemps. It holds the identity of a second
184 32-bit virtual HReg, which holds the high half
185 of the value.
sewardjc97096c2004-06-30 09:28:04 +0000186
187 - The code array, that is, the insns selected so far.
188
189 - A counter, for generating new virtual registers.
190
sewardje8e9d732004-07-16 21:03:45 +0000191 Note, this is all host-independent. */
sewardjc97096c2004-06-30 09:28:04 +0000192
193typedef
194 struct {
sewardj194d54a2004-07-03 19:08:18 +0000195 IRTypeEnv* type_env;
sewardjc97096c2004-06-30 09:28:04 +0000196
sewardje539a402004-07-14 18:24:17 +0000197 HReg* vregmap;
sewardje8e9d732004-07-16 21:03:45 +0000198 HReg* vregmapHI;
sewardj194d54a2004-07-03 19:08:18 +0000199 Int n_vregmap;
sewardjc97096c2004-06-30 09:28:04 +0000200
sewardj2cd80dc2004-07-02 15:20:40 +0000201 HInstrArray* code;
sewardjc97096c2004-06-30 09:28:04 +0000202
sewardj194d54a2004-07-03 19:08:18 +0000203 Int vreg_ctr;
sewardjc97096c2004-06-30 09:28:04 +0000204 }
205 ISelEnv;
206
207
208static HReg lookupIRTemp ( ISelEnv* env, IRTemp tmp )
209{
sewardje539a402004-07-14 18:24:17 +0000210 vassert(tmp >= 0);
211 vassert(tmp < env->n_vregmap);
212 return env->vregmap[tmp];
sewardjc97096c2004-06-30 09:28:04 +0000213}
214
sewardj597b71b2004-07-19 02:51:12 +0000215static void lookupIRTemp64 ( HReg* vrHI, HReg* vrLO, ISelEnv* env, IRTemp tmp )
sewardje8e9d732004-07-16 21:03:45 +0000216{
217 vassert(tmp >= 0);
218 vassert(tmp < env->n_vregmap);
sewardj597b71b2004-07-19 02:51:12 +0000219 vassert(env->vregmapHI[tmp] != INVALID_HREG);
sewardje8e9d732004-07-16 21:03:45 +0000220 *vrLO = env->vregmap[tmp];
221 *vrHI = env->vregmapHI[tmp];
222}
223
sewardj2cd80dc2004-07-02 15:20:40 +0000224static void addInstr ( ISelEnv* env, X86Instr* instr )
sewardjc97096c2004-06-30 09:28:04 +0000225{
sewardj2cd80dc2004-07-02 15:20:40 +0000226 addHInstr(env->code, instr);
sewardjf48ac192004-10-29 00:41:29 +0000227 if (vex_traceflags & VEX_TRACE_VCODE) {
sewardj1f40a0a2004-07-21 12:28:07 +0000228 ppX86Instr(instr);
229 vex_printf("\n");
230 }
sewardjc97096c2004-06-30 09:28:04 +0000231}
232
233static HReg newVRegI ( ISelEnv* env )
234{
sewardj4a31b262004-12-01 02:24:44 +0000235 HReg reg = mkHReg(env->vreg_ctr, HRcInt32, True/*virtual reg*/);
sewardj194d54a2004-07-03 19:08:18 +0000236 env->vreg_ctr++;
sewardjc97096c2004-06-30 09:28:04 +0000237 return reg;
238}
239
sewardj3196daf2004-08-13 00:18:58 +0000240static HReg newVRegF ( ISelEnv* env )
241{
sewardj4a31b262004-12-01 02:24:44 +0000242 HReg reg = mkHReg(env->vreg_ctr, HRcFlt64, True/*virtual reg*/);
sewardj3196daf2004-08-13 00:18:58 +0000243 env->vreg_ctr++;
244 return reg;
245}
246
sewardjd08f2d72004-12-01 23:19:36 +0000247static HReg newVRegV ( ISelEnv* env )
248{
249 HReg reg = mkHReg(env->vreg_ctr, HRcVec128, True/*virtual reg*/);
250 env->vreg_ctr++;
251 return reg;
252}
253
sewardj66f2f792004-06-30 16:37:16 +0000254
sewardjd18d1bf2004-08-25 12:49:22 +0000255/*---------------------------------------------------------*/
256/*--- ISEL: Forward declarations ---*/
257/*---------------------------------------------------------*/
258
259/* These are organised as iselXXX and iselXXX_wrk pairs. The
260 iselXXX_wrk do the real work, but are not to be called directly.
261 For each XXX, iselXXX calls its iselXXX_wrk counterpart, then
sewardjd08f2d72004-12-01 23:19:36 +0000262 checks that all returned registers are virtual. You should not
263 call the _wrk version directly.
sewardjd18d1bf2004-08-25 12:49:22 +0000264*/
sewardjd08f2d72004-12-01 23:19:36 +0000265static X86RMI* iselIntExpr_RMI_wrk ( ISelEnv* env, IRExpr* e );
266static X86RMI* iselIntExpr_RMI ( ISelEnv* env, IRExpr* e );
sewardjd18d1bf2004-08-25 12:49:22 +0000267
sewardjd08f2d72004-12-01 23:19:36 +0000268static X86RI* iselIntExpr_RI_wrk ( ISelEnv* env, IRExpr* e );
269static X86RI* iselIntExpr_RI ( ISelEnv* env, IRExpr* e );
sewardjd18d1bf2004-08-25 12:49:22 +0000270
sewardjd08f2d72004-12-01 23:19:36 +0000271static X86RM* iselIntExpr_RM_wrk ( ISelEnv* env, IRExpr* e );
272static X86RM* iselIntExpr_RM ( ISelEnv* env, IRExpr* e );
sewardjd18d1bf2004-08-25 12:49:22 +0000273
sewardjd08f2d72004-12-01 23:19:36 +0000274static HReg iselIntExpr_R_wrk ( ISelEnv* env, IRExpr* e );
275static HReg iselIntExpr_R ( ISelEnv* env, IRExpr* e );
sewardjd18d1bf2004-08-25 12:49:22 +0000276
sewardjd08f2d72004-12-01 23:19:36 +0000277static X86AMode* iselIntExpr_AMode_wrk ( ISelEnv* env, IRExpr* e );
278static X86AMode* iselIntExpr_AMode ( ISelEnv* env, IRExpr* e );
sewardjd18d1bf2004-08-25 12:49:22 +0000279
sewardjd08f2d72004-12-01 23:19:36 +0000280static void iselInt64Expr_wrk ( HReg* rHi, HReg* rLo,
281 ISelEnv* env, IRExpr* e );
282static void iselInt64Expr ( HReg* rHi, HReg* rLo,
283 ISelEnv* env, IRExpr* e );
sewardjd18d1bf2004-08-25 12:49:22 +0000284
285static X86CondCode iselCondCode_wrk ( ISelEnv* env, IRExpr* e );
286static X86CondCode iselCondCode ( ISelEnv* env, IRExpr* e );
287
sewardjd08f2d72004-12-01 23:19:36 +0000288static HReg iselDblExpr_wrk ( ISelEnv* env, IRExpr* e );
289static HReg iselDblExpr ( ISelEnv* env, IRExpr* e );
290
291static HReg iselFltExpr_wrk ( ISelEnv* env, IRExpr* e );
292static HReg iselFltExpr ( ISelEnv* env, IRExpr* e );
293
294static HReg iselVecExpr_wrk ( ISelEnv* env, IRExpr* e );
295static HReg iselVecExpr ( ISelEnv* env, IRExpr* e );
sewardj89cd0932004-09-08 18:23:25 +0000296
sewardjd18d1bf2004-08-25 12:49:22 +0000297
298/*---------------------------------------------------------*/
sewardj17442fe2004-09-20 14:54:28 +0000299/*--- ISEL: Misc helpers ---*/
300/*---------------------------------------------------------*/
301
sewardjd4a4d012004-11-08 18:53:52 +0000302/* Is this a 32-bit zero expression? */
303
304static Bool isZero32 ( IRExpr* e )
305{
306 return e->tag == Iex_Const
307 && e->Iex.Const.con->tag == Ico_U32
308 && e->Iex.Const.con->Ico.U32 == 0;
309}
310
sewardj17442fe2004-09-20 14:54:28 +0000311/* Make a int reg-reg move. */
312
sewardjd08f2d72004-12-01 23:19:36 +0000313static X86Instr* mk_iMOVsd_RR ( HReg src, HReg dst )
sewardj17442fe2004-09-20 14:54:28 +0000314{
sewardj4a31b262004-12-01 02:24:44 +0000315 vassert(hregClass(src) == HRcInt32);
316 vassert(hregClass(dst) == HRcInt32);
sewardj17442fe2004-09-20 14:54:28 +0000317 return X86Instr_Alu32R(Xalu_MOV, X86RMI_Reg(src), dst);
318}
319
sewardj77352542004-10-30 20:39:01 +0000320
sewardjd08f2d72004-12-01 23:19:36 +0000321/* Make a vector reg-reg move. */
322
323static X86Instr* mk_vMOVsd_RR ( HReg src, HReg dst )
324{
325 vassert(hregClass(src) == HRcVec128);
326 vassert(hregClass(dst) == HRcVec128);
sewardj9e203592004-12-10 01:48:18 +0000327 return X86Instr_SseReRg(Xsse_MOV, src, dst);
sewardjd08f2d72004-12-01 23:19:36 +0000328}
329
sewardj129b3d92004-12-05 15:42:05 +0000330/* Advance/retreat %esp by n. */
331
sewardj855f32d2004-12-05 21:22:38 +0000332static void add_to_esp ( ISelEnv* env, Int n )
sewardj129b3d92004-12-05 15:42:05 +0000333{
334 vassert(n > 0 && n < 256 && (n%4) == 0);
335 addInstr(env,
336 X86Instr_Alu32R(Xalu_ADD, X86RMI_Imm(n), hregX86_ESP()));
337}
338
sewardj855f32d2004-12-05 21:22:38 +0000339static void sub_from_esp ( ISelEnv* env, Int n )
sewardj129b3d92004-12-05 15:42:05 +0000340{
341 vassert(n > 0 && n < 256 && (n%4) == 0);
342 addInstr(env,
343 X86Instr_Alu32R(Xalu_SUB, X86RMI_Imm(n), hregX86_ESP()));
344}
345
sewardjd08f2d72004-12-01 23:19:36 +0000346
sewardj218e29f2004-11-07 18:45:15 +0000347/* Given an amode, return one which references 4 bytes further
348 along. */
349
350static X86AMode* advance4 ( X86AMode* am )
351{
352 X86AMode* am4 = dopyX86AMode(am);
sewardj464efa42004-11-19 22:17:29 +0000353 switch (am4->tag) {
354 case Xam_IRRS:
355 am4->Xam.IRRS.imm += 4; break;
356 case Xam_IR:
357 am4->Xam.IR.imm += 4; break;
358 default:
359 vpanic("advance4(x86,host)");
360 }
sewardj218e29f2004-11-07 18:45:15 +0000361 return am4;
362}
363
364
sewardj17442fe2004-09-20 14:54:28 +0000365/* Push an arg onto the host stack, in preparation for a call to a
366 helper function of some kind. Returns the number of 32-bit words
367 pushed. */
368
369static Int pushArg ( ISelEnv* env, IRExpr* arg )
370{
371 IRType arg_ty = typeOfIRExpr(env->type_env, arg);
372 if (arg_ty == Ity_I32) {
373 addInstr(env, X86Instr_Push(iselIntExpr_RMI(env, arg)));
374 return 1;
375 } else
376 if (arg_ty == Ity_I64) {
377 HReg rHi, rLo;
sewardjd08f2d72004-12-01 23:19:36 +0000378 iselInt64Expr(&rHi, &rLo, env, arg);
sewardj17442fe2004-09-20 14:54:28 +0000379 addInstr(env, X86Instr_Push(X86RMI_Reg(rHi)));
380 addInstr(env, X86Instr_Push(X86RMI_Reg(rLo)));
381 return 2;
382 }
383 ppIRExpr(arg);
384 vpanic("pushArg(x86): can't handle arg of this type");
385}
386
sewardjc5fc7aa2004-10-27 23:00:55 +0000387
sewardj17442fe2004-09-20 14:54:28 +0000388/* Complete the call to a helper function, by calling the
389 helper and clearing the args off the stack. */
390
391static
sewardj4b861de2004-11-03 15:24:42 +0000392void callHelperAndClearArgs ( ISelEnv* env, X86CondCode cc,
393 IRCallee* cee, Int n_arg_ws )
sewardj17442fe2004-09-20 14:54:28 +0000394{
sewardj77352542004-10-30 20:39:01 +0000395 /* Complication. Need to decide which reg to use as the fn address
396 pointer, in a way that doesn't trash regparm-passed
397 parameters. */
sewardjf9655262004-10-31 20:02:16 +0000398 vassert(sizeof(void*) == 4);
sewardj77352542004-10-30 20:39:01 +0000399
sewardj4b861de2004-11-03 15:24:42 +0000400 addInstr(env, X86Instr_Call( cc, (UInt)cee->addr, cee->regparms));
sewardj17442fe2004-09-20 14:54:28 +0000401 if (n_arg_ws > 0)
sewardj855f32d2004-12-05 21:22:38 +0000402 add_to_esp(env, 4*n_arg_ws);
sewardj17442fe2004-09-20 14:54:28 +0000403}
404
sewardj77352542004-10-30 20:39:01 +0000405
sewardj108b3012004-11-17 13:06:21 +0000406/* Used only in doHelperCall. See big comment in doHelperCall re
407 handling of regparm args. This function figures out whether
408 evaluation of an expression might require use of a fixed register.
409 If in doubt return True (safe but suboptimal).
410*/
411static
412Bool mightRequireFixedRegs ( IRExpr* e )
413{
414 switch (e->tag) {
415 case Iex_Tmp: case Iex_Const: case Iex_Get:
416 return False;
417 default:
418 return True;
419 }
420}
421
422
sewardj4b861de2004-11-03 15:24:42 +0000423/* Do a complete function call. guard is a Ity_Bit expression
424 indicating whether or not the call happens. If guard==NULL, the
425 call is unconditional. */
sewardj77352542004-10-30 20:39:01 +0000426
427static
428void doHelperCall ( ISelEnv* env,
sewardj4b861de2004-11-03 15:24:42 +0000429 Bool passBBP,
430 IRExpr* guard, IRCallee* cee, IRExpr** args )
sewardj77352542004-10-30 20:39:01 +0000431{
sewardj4b861de2004-11-03 15:24:42 +0000432 X86CondCode cc;
sewardj108b3012004-11-17 13:06:21 +0000433 HReg argregs[3];
434 HReg tmpregs[3];
435 Bool danger;
436 Int not_done_yet, n_args, n_arg_ws, stack_limit,
437 i, argreg, argregX;
sewardj77352542004-10-30 20:39:01 +0000438
439 /* Marshal args for a call, do the call, and clear the stack.
440 Complexities to consider:
441
442 * if passBBP is True, %ebp (the baseblock pointer) is to be
443 passed as the first arg.
444
445 * If the callee claims regparmness of 1, 2 or 3, we must pass the
446 first 1, 2 or 3 args in registers (EAX, EDX, and ECX
447 respectively). To keep things relatively simple, only args of
448 type I32 may be passed as regparms -- just bomb out if anything
449 else turns up. Clearly this depends on the front ends not
450 trying to pass any other types as regparms.
451 */
452
sewardj108b3012004-11-17 13:06:21 +0000453 /* 16 Nov 2004: the regparm handling is complicated by the
454 following problem.
455
456 Consider a call two a function with two regparm parameters:
457 f(e1,e2). We need to compute e1 into %eax and e2 into %edx.
458 Suppose code is first generated to compute e1 into %eax. Then,
459 code is generated to compute e2 into %edx. Unfortunately, if
460 the latter code sequence uses %eax, it will trash the value of
461 e1 computed by the former sequence. This could happen if (for
462 example) e2 itself involved a function call. In the code below,
463 args are evaluated right-to-left, not left-to-right, but the
464 principle and the problem are the same.
465
466 One solution is to compute all regparm-bound args into vregs
467 first, and once they are all done, move them to the relevant
468 real regs. This always gives correct code, but it also gives
469 a bunch of vreg-to-rreg moves which are usually redundant but
470 are hard for the register allocator to get rid of.
471
472 A compromise is to first examine all regparm'd argument
473 expressions. If they are all so simple that it is clear
474 they will be evaluated without use of any fixed registers,
475 use the old compute-directly-to-fixed-target scheme. If not,
476 be safe and use the via-vregs scheme.
477
478 Note this requires being able to examine an expression and
479 determine whether or not evaluation of it might use a fixed
480 register. That requires knowledge of how the rest of this
481 insn selector works. Currently just the following 3 are
482 regarded as safe -- hopefully they cover the majority of
483 arguments in practice: IRExpr_Tmp IRExpr_Const IRExpr_Get.
484 */
sewardj77352542004-10-30 20:39:01 +0000485 vassert(cee->regparms >= 0 && cee->regparms <= 3);
486
487 n_args = n_arg_ws = 0;
488 while (args[n_args]) n_args++;
489
sewardj11eebbe2004-10-30 22:20:02 +0000490 not_done_yet = n_args;
491 if (passBBP)
492 not_done_yet++;
493
sewardj77352542004-10-30 20:39:01 +0000494 stack_limit = cee->regparms;
495 if (cee->regparms > 0 && passBBP) stack_limit--;
496
sewardj108b3012004-11-17 13:06:21 +0000497 /* ------ BEGIN marshall all arguments ------ */
498
sewardj11eebbe2004-10-30 22:20:02 +0000499 /* Push (R to L) the stack-passed args, [n_args-1 .. stack_limit] */
500 for (i = n_args-1; i >= stack_limit; i--) {
sewardj77352542004-10-30 20:39:01 +0000501 n_arg_ws += pushArg(env, args[i]);
sewardj11eebbe2004-10-30 22:20:02 +0000502 not_done_yet--;
503 }
sewardj77352542004-10-30 20:39:01 +0000504
505 /* args [stack_limit-1 .. 0] and possibly %ebp are to be passed in
506 registers. */
sewardj77352542004-10-30 20:39:01 +0000507
508 if (cee->regparms > 0) {
sewardj108b3012004-11-17 13:06:21 +0000509
510 /* ------ BEGIN deal with regparms ------ */
511
sewardj77352542004-10-30 20:39:01 +0000512 /* deal with regparms, not forgetting %ebp if needed. */
513 argregs[0] = hregX86_EAX();
514 argregs[1] = hregX86_EDX();
515 argregs[2] = hregX86_ECX();
sewardj108b3012004-11-17 13:06:21 +0000516 tmpregs[0] = tmpregs[1] = tmpregs[2] = INVALID_HREG;
517
sewardj77352542004-10-30 20:39:01 +0000518 argreg = cee->regparms;
519
sewardj108b3012004-11-17 13:06:21 +0000520 /* In keeping with big comment above, detect potential danger
521 and use the via-vregs scheme if needed. */
522 danger = False;
sewardj77352542004-10-30 20:39:01 +0000523 for (i = stack_limit-1; i >= 0; i--) {
sewardj108b3012004-11-17 13:06:21 +0000524 if (mightRequireFixedRegs(args[i])) {
525 danger = True;
526 break;
527 }
sewardj77352542004-10-30 20:39:01 +0000528 }
sewardj108b3012004-11-17 13:06:21 +0000529
530 if (danger) {
531
532 /* Move via temporaries */
533 argregX = argreg;
534 for (i = stack_limit-1; i >= 0; i--) {
535
536 if (0) {
537 vex_printf("x86 host: register param is complex: ");
538 ppIRExpr(args[i]);
539 vex_printf("\n");
540 }
541
542 argreg--;
543 vassert(argreg >= 0);
544 vassert(typeOfIRExpr(env->type_env, args[i]) == Ity_I32);
545 tmpregs[argreg] = iselIntExpr_R(env, args[i]);
546 not_done_yet--;
547 }
548 for (i = stack_limit-1; i >= 0; i--) {
549 argregX--;
550 vassert(argregX >= 0);
sewardjd08f2d72004-12-01 23:19:36 +0000551 addInstr( env, mk_iMOVsd_RR( tmpregs[argregX], argregs[argregX] ) );
sewardj108b3012004-11-17 13:06:21 +0000552 }
553
554 } else {
555 /* It's safe to compute all regparm args directly into their
556 target registers. */
557 for (i = stack_limit-1; i >= 0; i--) {
558 argreg--;
559 vassert(argreg >= 0);
560 vassert(typeOfIRExpr(env->type_env, args[i]) == Ity_I32);
561 addInstr(env, X86Instr_Alu32R(Xalu_MOV,
562 iselIntExpr_RMI(env, args[i]),
563 argregs[argreg]));
564 not_done_yet--;
565 }
566
567 }
568
569 /* Not forgetting %ebp if needed. */
sewardj77352542004-10-30 20:39:01 +0000570 if (passBBP) {
571 vassert(argreg == 1);
sewardjd08f2d72004-12-01 23:19:36 +0000572 addInstr(env, mk_iMOVsd_RR( hregX86_EBP(), argregs[0]));
sewardj11eebbe2004-10-30 22:20:02 +0000573 not_done_yet--;
sewardj77352542004-10-30 20:39:01 +0000574 }
sewardj108b3012004-11-17 13:06:21 +0000575
576 /* ------ END deal with regparms ------ */
577
sewardj77352542004-10-30 20:39:01 +0000578 } else {
sewardj108b3012004-11-17 13:06:21 +0000579
sewardj77352542004-10-30 20:39:01 +0000580 /* No regparms. Heave %ebp on the stack if needed. */
581 if (passBBP) {
582 addInstr(env, X86Instr_Push(X86RMI_Reg(hregX86_EBP())));
583 n_arg_ws++;
sewardj11eebbe2004-10-30 22:20:02 +0000584 not_done_yet--;
sewardj77352542004-10-30 20:39:01 +0000585 }
sewardj108b3012004-11-17 13:06:21 +0000586
sewardj77352542004-10-30 20:39:01 +0000587 }
588
sewardj11eebbe2004-10-30 22:20:02 +0000589 vassert(not_done_yet == 0);
590
sewardj108b3012004-11-17 13:06:21 +0000591 /* ------ END marshall all arguments ------ */
592
sewardj4b861de2004-11-03 15:24:42 +0000593 /* Now we can compute the condition. We can't do it earlier
594 because the argument computations could trash the condition
595 codes. Be a bit clever to handle the common case where the
596 guard is 1:Bit. */
597 cc = Xcc_ALWAYS;
598 if (guard) {
599 if (guard->tag == Iex_Const
sewardjba999312004-11-15 15:21:17 +0000600 && guard->Iex.Const.con->tag == Ico_U1
601 && guard->Iex.Const.con->Ico.U1 == True) {
sewardj4b861de2004-11-03 15:24:42 +0000602 /* unconditional -- do nothing */
603 } else {
604 cc = iselCondCode( env, guard );
605 }
606 }
607
sewardj77352542004-10-30 20:39:01 +0000608 /* call the helper, and get the args off the stack afterwards. */
sewardj4b861de2004-11-03 15:24:42 +0000609 callHelperAndClearArgs( env, cc, cee, n_arg_ws );
sewardj77352542004-10-30 20:39:01 +0000610}
611
612
sewardj2d3f77c2004-09-22 23:49:09 +0000613/* Given a guest-state array descriptor, an index expression and a
614 bias, generate an X86AMode holding the relevant guest state
615 offset. */
616
617static
618X86AMode* genGuestArrayOffset ( ISelEnv* env, IRArray* descr,
619 IRExpr* off, Int bias )
620{
sewardj8fc93742004-11-22 11:29:33 +0000621 HReg tmp, roff;
622 Int elemSz = sizeofIRType(descr->elemTy);
623 Int nElems = descr->nElems;
sewardj2d3f77c2004-09-22 23:49:09 +0000624
625 /* throw out any cases not generated by an x86 front end. In
626 theory there might be a day where we need to handle them -- if
627 we ever run non-x86-guest on x86 host. */
628
629 if (nElems != 8 || (elemSz != 1 && elemSz != 8))
630 vpanic("genGuestArrayOffset(x86 host)");
631
632 /* Compute off into a reg, %off. Then return:
633
634 movl %off, %tmp
635 addl $bias, %tmp (if bias != 0)
636 andl %tmp, 7
637 ... base(%ebp, %tmp, shift) ...
638 */
sewardj8fc93742004-11-22 11:29:33 +0000639 tmp = newVRegI(env);
640 roff = iselIntExpr_R(env, off);
sewardjd08f2d72004-12-01 23:19:36 +0000641 addInstr(env, mk_iMOVsd_RR(roff, tmp));
sewardj2d3f77c2004-09-22 23:49:09 +0000642 if (bias != 0) {
643 addInstr(env,
644 X86Instr_Alu32R(Xalu_ADD, X86RMI_Imm(bias), tmp));
645 }
646 addInstr(env,
647 X86Instr_Alu32R(Xalu_AND, X86RMI_Imm(7), tmp));
648 vassert(elemSz == 1 || elemSz == 8);
649 return
650 X86AMode_IRRS( descr->base, hregX86_EBP(), tmp,
651 elemSz==8 ? 3 : 0);
652}
653
sewardj17442fe2004-09-20 14:54:28 +0000654
sewardj4cb918d2004-12-03 19:43:31 +0000655/* Mess with the FPU's rounding mode: set to the default rounding mode
656 (0x037F). */
657static
658void set_FPU_rounding_default ( ISelEnv* env )
659{
660 /* pushl $0x037F
661 fldcw 0(%esp)
662 addl $4, %esp
663 */
664 X86AMode* zero_esp = X86AMode_IR(0, hregX86_ESP());
665 addInstr(env, X86Instr_Push(X86RMI_Imm(0x037F)));
666 addInstr(env, X86Instr_FpLdStCW(True/*load*/, zero_esp));
sewardj855f32d2004-12-05 21:22:38 +0000667 add_to_esp(env, 4);
sewardj4cb918d2004-12-03 19:43:31 +0000668}
669
670
671/* Mess with the FPU's rounding mode: 'mode' is an I32-typed
672 expression denoting a value in the range 0 .. 3, indicating a round
673 mode encoded as per type IRRoundingMode. Set the x87 FPU to have
674 the same rounding.
675*/
676static
677void set_FPU_rounding_mode ( ISelEnv* env, IRExpr* mode )
678{
679 HReg rrm = iselIntExpr_R(env, mode);
680 HReg rrm2 = newVRegI(env);
681 X86AMode* zero_esp = X86AMode_IR(0, hregX86_ESP());
682
683 /* movl %rrm, %rrm2
684 andl $3, %rrm2 -- shouldn't be needed; paranoia
685 shll $10, %rrm2
686 orl $0x037F, %rrm2
687 pushl %rrm2
688 fldcw 0(%esp)
689 addl $4, %esp
690 */
691 addInstr(env, mk_iMOVsd_RR(rrm, rrm2));
692 addInstr(env, X86Instr_Alu32R(Xalu_AND, X86RMI_Imm(3), rrm2));
693 addInstr(env, X86Instr_Sh32(Xsh_SHL, 10, X86RM_Reg(rrm2)));
694 addInstr(env, X86Instr_Alu32R(Xalu_OR, X86RMI_Imm(0x037F), rrm2));
695 addInstr(env, X86Instr_Push(X86RMI_Reg(rrm2)));
696 addInstr(env, X86Instr_FpLdStCW(True/*load*/, zero_esp));
sewardj855f32d2004-12-05 21:22:38 +0000697 add_to_esp(env, 4);
sewardj4cb918d2004-12-03 19:43:31 +0000698}
699
700
sewardj17442fe2004-09-20 14:54:28 +0000701/*---------------------------------------------------------*/
sewardjd18d1bf2004-08-25 12:49:22 +0000702/*--- ISEL: Integer expressions (32/16/8 bit) ---*/
703/*---------------------------------------------------------*/
704
sewardjc97096c2004-06-30 09:28:04 +0000705/* Select insns for an integer-typed expression, and add them to the
sewardjd18d1bf2004-08-25 12:49:22 +0000706 code list. Return a reg holding the result. This reg will be a
707 virtual register. THE RETURNED REG MUST NOT BE MODIFIED. If you
708 want to modify it, ask for a new vreg, copy it in there, and modify
709 the copy. The register allocator will do its best to map both
710 vregs to the same real register, so the copies will often disappear
711 later in the game.
sewardj4042c7e2004-07-18 01:28:30 +0000712
713 This should handle expressions of 32, 16 and 8-bit type. All
714 results are returned in a 32-bit register. For 16- and 8-bit
sewardjd18d1bf2004-08-25 12:49:22 +0000715 expressions, the upper 16/24 bits are arbitrary, so you should mask
716 or sign extend partial values if necessary.
sewardjc97096c2004-06-30 09:28:04 +0000717*/
sewardjd18d1bf2004-08-25 12:49:22 +0000718
sewardj66f2f792004-06-30 16:37:16 +0000719static HReg iselIntExpr_R ( ISelEnv* env, IRExpr* e )
sewardjc97096c2004-06-30 09:28:04 +0000720{
sewardjd18d1bf2004-08-25 12:49:22 +0000721 HReg r = iselIntExpr_R_wrk(env, e);
722 /* sanity checks ... */
723# if 0
724 vex_printf("\n"); ppIRExpr(e); vex_printf("\n");
725# endif
sewardj4a31b262004-12-01 02:24:44 +0000726 vassert(hregClass(r) == HRcInt32);
sewardjd18d1bf2004-08-25 12:49:22 +0000727 vassert(hregIsVirtual(r));
728 return r;
729}
730
731/* DO NOT CALL THIS DIRECTLY ! */
732static HReg iselIntExpr_R_wrk ( ISelEnv* env, IRExpr* e )
733{
sewardj443cd9d2004-07-18 23:06:45 +0000734 MatchInfo mi;
sewardj84ff0652004-08-23 16:16:08 +0000735 DECLARE_PATTERN(p_32to1_then_1Uto8);
sewardj443cd9d2004-07-18 23:06:45 +0000736
sewardje8e9d732004-07-16 21:03:45 +0000737 IRType ty = typeOfIRExpr(env->type_env,e);
sewardj4042c7e2004-07-18 01:28:30 +0000738 vassert(ty == Ity_I32 || Ity_I16 || Ity_I8);
sewardjc97096c2004-06-30 09:28:04 +0000739
740 switch (e->tag) {
741
sewardj60f4e3c2004-07-19 01:56:50 +0000742 /* --------- TEMP --------- */
sewardje8e9d732004-07-16 21:03:45 +0000743 case Iex_Tmp: {
sewardje8e9d732004-07-16 21:03:45 +0000744 return lookupIRTemp(env, e->Iex.Tmp.tmp);
745 }
sewardjc97096c2004-06-30 09:28:04 +0000746
sewardj60f4e3c2004-07-19 01:56:50 +0000747 /* --------- LOAD --------- */
sewardje8e9d732004-07-16 21:03:45 +0000748 case Iex_LDle: {
sewardje8e9d732004-07-16 21:03:45 +0000749 HReg dst = newVRegI(env);
sewardj4042c7e2004-07-18 01:28:30 +0000750 X86AMode* amode = iselIntExpr_AMode ( env, e->Iex.LDle.addr );
751 if (ty == Ity_I32) {
752 addInstr(env, X86Instr_Alu32R(Xalu_MOV,
753 X86RMI_Mem(amode), dst) );
754 return dst;
755 }
756 if (ty == Ity_I16) {
757 addInstr(env, X86Instr_LoadEX(2,False,amode,dst));
758 return dst;
759 }
sewardj443cd9d2004-07-18 23:06:45 +0000760 if (ty == Ity_I8) {
761 addInstr(env, X86Instr_LoadEX(1,False,amode,dst));
762 return dst;
763 }
sewardj4042c7e2004-07-18 01:28:30 +0000764 break;
sewardje8e9d732004-07-16 21:03:45 +0000765 }
766
sewardj60f4e3c2004-07-19 01:56:50 +0000767 /* --------- BINARY OP --------- */
sewardje8e9d732004-07-16 21:03:45 +0000768 case Iex_Binop: {
769 X86AluOp aluOp;
770 X86ShiftOp shOp;
sewardj8c7f1ab2004-07-29 20:31:09 +0000771
sewardjd4a4d012004-11-08 18:53:52 +0000772 /* Pattern: Sub32(0,x) */
773 if (e->Iex.Binop.op == Iop_Sub32 && isZero32(e->Iex.Binop.arg1)) {
774 HReg dst = newVRegI(env);
775 HReg reg = iselIntExpr_R(env, e->Iex.Binop.arg2);
sewardjd08f2d72004-12-01 23:19:36 +0000776 addInstr(env, mk_iMOVsd_RR(reg,dst));
sewardjd4a4d012004-11-08 18:53:52 +0000777 addInstr(env, X86Instr_Unary32(Xun_NEG,X86RM_Reg(dst)));
778 return dst;
779 }
780
sewardj4042c7e2004-07-18 01:28:30 +0000781 /* Is it an addition or logical style op? */
sewardje8e9d732004-07-16 21:03:45 +0000782 switch (e->Iex.Binop.op) {
sewardja2384712004-07-29 14:36:40 +0000783 case Iop_Add8: case Iop_Add16: case Iop_Add32:
sewardj1813dbe2004-07-28 17:09:04 +0000784 aluOp = Xalu_ADD; break;
sewardj60f4e3c2004-07-19 01:56:50 +0000785 case Iop_Sub8: case Iop_Sub16: case Iop_Sub32:
786 aluOp = Xalu_SUB; break;
sewardj5c34dc92004-07-19 12:48:11 +0000787 case Iop_And8: case Iop_And16: case Iop_And32:
788 aluOp = Xalu_AND; break;
sewardj750f4072004-07-26 22:39:11 +0000789 case Iop_Or8: case Iop_Or16: case Iop_Or32:
sewardj597b71b2004-07-19 02:51:12 +0000790 aluOp = Xalu_OR; break;
sewardja2384712004-07-29 14:36:40 +0000791 case Iop_Xor8: case Iop_Xor16: case Iop_Xor32:
sewardj597b71b2004-07-19 02:51:12 +0000792 aluOp = Xalu_XOR; break;
sewardjb81f8b32004-07-30 10:17:50 +0000793 case Iop_Mul16: case Iop_Mul32:
794 aluOp = Xalu_MUL; break;
795 default:
796 aluOp = Xalu_INVALID; break;
sewardje8e9d732004-07-16 21:03:45 +0000797 }
798 /* For commutative ops we assume any literal
sewardj66f2f792004-06-30 16:37:16 +0000799 values are on the second operand. */
sewardje8e9d732004-07-16 21:03:45 +0000800 if (aluOp != Xalu_INVALID) {
sewardj66f2f792004-06-30 16:37:16 +0000801 HReg dst = newVRegI(env);
802 HReg reg = iselIntExpr_R(env, e->Iex.Binop.arg1);
803 X86RMI* rmi = iselIntExpr_RMI(env, e->Iex.Binop.arg2);
sewardjd08f2d72004-12-01 23:19:36 +0000804 addInstr(env, mk_iMOVsd_RR(reg,dst));
sewardje8e9d732004-07-16 21:03:45 +0000805 addInstr(env, X86Instr_Alu32R(aluOp, rmi, dst));
sewardj66f2f792004-06-30 16:37:16 +0000806 return dst;
sewardjc97096c2004-06-30 09:28:04 +0000807 }
sewardj4f391492004-08-24 22:45:30 +0000808 /* Could do better here; forcing the first arg into a reg
809 isn't always clever.
810 -- t70 = Xor32(And32(Xor32(LDle:I32(Add32(t41,0xFFFFFFA0:I32)),
811 LDle:I32(Add32(t41,0xFFFFFFA4:I32))),LDle:I32(Add32(
812 t41,0xFFFFFFA8:I32))),LDle:I32(Add32(t41,0xFFFFFFA0:I32)))
813 movl 0xFFFFFFA0(%vr41),%vr107
814 movl 0xFFFFFFA4(%vr41),%vr108
815 movl %vr107,%vr106
816 xorl %vr108,%vr106
817 movl 0xFFFFFFA8(%vr41),%vr109
818 movl %vr106,%vr105
819 andl %vr109,%vr105
820 movl 0xFFFFFFA0(%vr41),%vr110
821 movl %vr105,%vr104
822 xorl %vr110,%vr104
823 movl %vr104,%vr70
824 */
sewardj8c7f1ab2004-07-29 20:31:09 +0000825
sewardj4042c7e2004-07-18 01:28:30 +0000826 /* Perhaps a shift op? */
sewardje8e9d732004-07-16 21:03:45 +0000827 switch (e->Iex.Binop.op) {
sewardj1813dbe2004-07-28 17:09:04 +0000828 case Iop_Shl32: case Iop_Shl16: case Iop_Shl8:
829 shOp = Xsh_SHL; break;
830 case Iop_Shr32: case Iop_Shr16: case Iop_Shr8:
sewardj5c34dc92004-07-19 12:48:11 +0000831 shOp = Xsh_SHR; break;
sewardj8c7f1ab2004-07-29 20:31:09 +0000832 case Iop_Sar32: case Iop_Sar16: case Iop_Sar8:
sewardj1813dbe2004-07-28 17:09:04 +0000833 shOp = Xsh_SAR; break;
834 default:
835 shOp = Xsh_INVALID; break;
sewardje8e9d732004-07-16 21:03:45 +0000836 }
837 if (shOp != Xsh_INVALID) {
sewardj8c7f1ab2004-07-29 20:31:09 +0000838 HReg dst = newVRegI(env);
sewardj38ff3d82004-07-26 23:27:08 +0000839
840 /* regL = the value to be shifted */
sewardj96efe572004-07-03 14:48:24 +0000841 HReg regL = iselIntExpr_R(env, e->Iex.Binop.arg1);
sewardjd08f2d72004-12-01 23:19:36 +0000842 addInstr(env, mk_iMOVsd_RR(regL,dst));
sewardj38ff3d82004-07-26 23:27:08 +0000843
sewardj5c34dc92004-07-19 12:48:11 +0000844 /* Do any necessary widening for 16/8 bit operands */
845 switch (e->Iex.Binop.op) {
846 case Iop_Shr8:
847 addInstr(env, X86Instr_Alu32R(
848 Xalu_AND, X86RMI_Imm(0xFF), dst));
849 break;
850 case Iop_Shr16:
851 addInstr(env, X86Instr_Alu32R(
852 Xalu_AND, X86RMI_Imm(0xFFFF), dst));
853 break;
sewardj8c7f1ab2004-07-29 20:31:09 +0000854 case Iop_Sar8:
855 addInstr(env, X86Instr_Sh32(Xsh_SHL, 24, X86RM_Reg(dst)));
856 addInstr(env, X86Instr_Sh32(Xsh_SAR, 24, X86RM_Reg(dst)));
857 break;
858 case Iop_Sar16:
859 addInstr(env, X86Instr_Sh32(Xsh_SHL, 16, X86RM_Reg(dst)));
860 addInstr(env, X86Instr_Sh32(Xsh_SAR, 16, X86RM_Reg(dst)));
861 break;
sewardj5c34dc92004-07-19 12:48:11 +0000862 default: break;
863 }
sewardj38ff3d82004-07-26 23:27:08 +0000864
865 /* Now consider the shift amount. If it's a literal, we
866 can do a much better job than the general case. */
867 if (e->Iex.Binop.arg2->tag == Iex_Const) {
868 /* assert that the IR is well-typed */
869 Int nshift;
870 vassert(e->Iex.Binop.arg2->Iex.Const.con->tag == Ico_U8);
sewardj38ff3d82004-07-26 23:27:08 +0000871 nshift = e->Iex.Binop.arg2->Iex.Const.con->Ico.U8;
sewardj3bd676c2004-07-27 10:50:38 +0000872 vassert(nshift >= 0);
sewardj38ff3d82004-07-26 23:27:08 +0000873 if (nshift > 0)
sewardjb81f8b32004-07-30 10:17:50 +0000874 /* Can't allow nshift==0 since that means %cl */
sewardj38ff3d82004-07-26 23:27:08 +0000875 addInstr(env, X86Instr_Sh32(
876 shOp,
877 nshift,
878 X86RM_Reg(dst)));
879 } else {
880 /* General case; we have to force the amount into %cl. */
881 HReg regR = iselIntExpr_R(env, e->Iex.Binop.arg2);
sewardjd08f2d72004-12-01 23:19:36 +0000882 addInstr(env, mk_iMOVsd_RR(regR,hregX86_ECX()));
sewardj38ff3d82004-07-26 23:27:08 +0000883 addInstr(env, X86Instr_Sh32(shOp, 0/* %cl */, X86RM_Reg(dst)));
884 }
sewardjd9c2b792004-07-08 01:44:38 +0000885 return dst;
886 }
sewardj8c7f1ab2004-07-29 20:31:09 +0000887
888 /* Handle misc other ops. */
sewardjfd332772004-11-09 16:01:40 +0000889 if (e->Iex.Binop.op == Iop_8HLto16) {
890 HReg hi8 = newVRegI(env);
891 HReg lo8 = newVRegI(env);
892 HReg hi8s = iselIntExpr_R(env, e->Iex.Binop.arg1);
893 HReg lo8s = iselIntExpr_R(env, e->Iex.Binop.arg2);
sewardjd08f2d72004-12-01 23:19:36 +0000894 addInstr(env, mk_iMOVsd_RR(hi8s, hi8));
895 addInstr(env, mk_iMOVsd_RR(lo8s, lo8));
sewardjfd332772004-11-09 16:01:40 +0000896 addInstr(env, X86Instr_Sh32(Xsh_SHL, 8, X86RM_Reg(hi8)));
897 addInstr(env, X86Instr_Alu32R(Xalu_AND, X86RMI_Imm(0xFF), lo8));
898 addInstr(env, X86Instr_Alu32R(Xalu_OR, X86RMI_Reg(lo8), hi8));
899 return hi8;
900 }
901
sewardj8c7f1ab2004-07-29 20:31:09 +0000902 if (e->Iex.Binop.op == Iop_16HLto32) {
903 HReg hi16 = newVRegI(env);
904 HReg lo16 = newVRegI(env);
905 HReg hi16s = iselIntExpr_R(env, e->Iex.Binop.arg1);
906 HReg lo16s = iselIntExpr_R(env, e->Iex.Binop.arg2);
sewardjd08f2d72004-12-01 23:19:36 +0000907 addInstr(env, mk_iMOVsd_RR(hi16s, hi16));
908 addInstr(env, mk_iMOVsd_RR(lo16s, lo16));
sewardj8c7f1ab2004-07-29 20:31:09 +0000909 addInstr(env, X86Instr_Sh32(Xsh_SHL, 16, X86RM_Reg(hi16)));
910 addInstr(env, X86Instr_Alu32R(Xalu_AND, X86RMI_Imm(0xFFFF), lo16));
911 addInstr(env, X86Instr_Alu32R(Xalu_OR, X86RMI_Reg(lo16), hi16));
912 return hi16;
913 }
914
sewardjb81f8b32004-07-30 10:17:50 +0000915 if (e->Iex.Binop.op == Iop_MullS16 || e->Iex.Binop.op == Iop_MullS8
916 || e->Iex.Binop.op == Iop_MullU16 || e->Iex.Binop.op == Iop_MullU8) {
917 HReg a16 = newVRegI(env);
918 HReg b16 = newVRegI(env);
919 HReg a16s = iselIntExpr_R(env, e->Iex.Binop.arg1);
920 HReg b16s = iselIntExpr_R(env, e->Iex.Binop.arg2);
921 Int shift = (e->Iex.Binop.op == Iop_MullS8
922 || e->Iex.Binop.op == Iop_MullU8)
923 ? 24 : 16;
924 X86ShiftOp shr_op = (e->Iex.Binop.op == Iop_MullS8
925 || e->Iex.Binop.op == Iop_MullS16)
926 ? Xsh_SAR : Xsh_SHR;
927
sewardjd08f2d72004-12-01 23:19:36 +0000928 addInstr(env, mk_iMOVsd_RR(a16s, a16));
929 addInstr(env, mk_iMOVsd_RR(b16s, b16));
sewardjb81f8b32004-07-30 10:17:50 +0000930 addInstr(env, X86Instr_Sh32(Xsh_SHL, shift, X86RM_Reg(a16)));
931 addInstr(env, X86Instr_Sh32(Xsh_SHL, shift, X86RM_Reg(b16)));
932 addInstr(env, X86Instr_Sh32(shr_op, shift, X86RM_Reg(a16)));
933 addInstr(env, X86Instr_Sh32(shr_op, shift, X86RM_Reg(b16)));
934 addInstr(env, X86Instr_Alu32R(Xalu_MUL, X86RMI_Reg(a16), b16));
935 return b16;
936 }
937
sewardjbdc7d212004-09-09 02:46:40 +0000938 if (e->Iex.Binop.op == Iop_CmpF64) {
939 HReg fL = iselDblExpr(env, e->Iex.Binop.arg1);
940 HReg fR = iselDblExpr(env, e->Iex.Binop.arg2);
941 HReg dst = newVRegI(env);
942 addInstr(env, X86Instr_FpCmp(fL,fR,dst));
943 /* shift this right 8 bits so as to conform to CmpF64
944 definition. */
945 addInstr(env, X86Instr_Sh32(Xsh_SHR, 8, X86RM_Reg(dst)));
946 return dst;
947 }
948
sewardj8f3debf2004-09-08 23:42:23 +0000949 if (e->Iex.Binop.op == Iop_F64toI32 || e->Iex.Binop.op == Iop_F64toI16) {
sewardj4cb918d2004-12-03 19:43:31 +0000950 Int sz = e->Iex.Binop.op == Iop_F64toI16 ? 2 : 4;
951 HReg rf = iselDblExpr(env, e->Iex.Binop.arg2);
952 HReg dst = newVRegI(env);
sewardj8f3debf2004-09-08 23:42:23 +0000953
954 /* Used several times ... */
955 X86AMode* zero_esp = X86AMode_IR(0, hregX86_ESP());
956
957 /* rf now holds the value to be converted, and rrm holds the
958 rounding mode value, encoded as per the IRRoundingMode
959 enum. The first thing to do is set the FPU's rounding
960 mode accordingly. */
961
sewardj4cb918d2004-12-03 19:43:31 +0000962 /* Create a space for the format conversion. */
sewardj8f3debf2004-09-08 23:42:23 +0000963 /* subl $4, %esp */
sewardj855f32d2004-12-05 21:22:38 +0000964 sub_from_esp(env, 4);
sewardj4cb918d2004-12-03 19:43:31 +0000965
966 /* Set host rounding mode */
967 set_FPU_rounding_mode( env, e->Iex.Binop.arg1 );
sewardj8f3debf2004-09-08 23:42:23 +0000968
969 /* gistw/l %rf, 0(%esp) */
970 addInstr(env, X86Instr_FpLdStI(False/*store*/, sz, rf, zero_esp));
971
972 if (sz == 2) {
973 /* movzwl 0(%esp), %dst */
974 addInstr(env, X86Instr_LoadEX(2,False,zero_esp,dst));
sewardj3bca9062004-12-04 14:36:09 +0000975 } else {
sewardj8f3debf2004-09-08 23:42:23 +0000976 /* movl 0(%esp), %dst */
977 vassert(sz == 4);
978 addInstr(env, X86Instr_Alu32R(
979 Xalu_MOV, X86RMI_Mem(zero_esp), dst));
980 }
981
sewardj4cb918d2004-12-03 19:43:31 +0000982 /* Restore default FPU rounding. */
983 set_FPU_rounding_default( env );
sewardj8f3debf2004-09-08 23:42:23 +0000984
985 /* addl $4, %esp */
sewardj855f32d2004-12-05 21:22:38 +0000986 add_to_esp(env, 4);
sewardj8f3debf2004-09-08 23:42:23 +0000987 return dst;
988 }
989
sewardj442d0be2004-10-15 22:57:13 +0000990 /* C3210 flags following FPU partial remainder (fprem), both
991 IEEE compliant (PREM1) and non-IEEE compliant (PREM). */
992 if (e->Iex.Binop.op == Iop_PRemC3210F64
993 || e->Iex.Binop.op == Iop_PRem1C3210F64) {
sewardj46de4072004-09-11 19:23:24 +0000994 HReg junk = newVRegF(env);
995 HReg dst = newVRegI(env);
996 HReg srcL = iselDblExpr(env, e->Iex.Binop.arg1);
997 HReg srcR = iselDblExpr(env, e->Iex.Binop.arg2);
sewardj442d0be2004-10-15 22:57:13 +0000998 addInstr(env, X86Instr_FpBinary(
sewardj855f32d2004-12-05 21:22:38 +0000999 e->Iex.Binop.op==Iop_PRemC3210F64
1000 ? Xfp_PREM : Xfp_PREM1,
sewardj442d0be2004-10-15 22:57:13 +00001001 srcL,srcR,junk
1002 ));
sewardj46de4072004-09-11 19:23:24 +00001003 /* The previous pseudo-insn will have left the FPU's C3210
1004 flags set correctly. So bag them. */
1005 addInstr(env, X86Instr_FpStSW_AX());
sewardjd08f2d72004-12-01 23:19:36 +00001006 addInstr(env, mk_iMOVsd_RR(hregX86_EAX(), dst));
sewardj46de4072004-09-11 19:23:24 +00001007 addInstr(env, X86Instr_Alu32R(Xalu_AND, X86RMI_Imm(0x4700), dst));
1008 return dst;
1009 }
1010
sewardje8e9d732004-07-16 21:03:45 +00001011 break;
sewardjd9c2b792004-07-08 01:44:38 +00001012 }
1013
sewardj60f4e3c2004-07-19 01:56:50 +00001014 /* --------- UNARY OP --------- */
sewardj4042c7e2004-07-18 01:28:30 +00001015 case Iex_Unop: {
sewardj443cd9d2004-07-18 23:06:45 +00001016 /* 1Uto8(32to1(expr32)) */
1017 DEFINE_PATTERN(p_32to1_then_1Uto8,
sewardj38ff3d82004-07-26 23:27:08 +00001018 unop(Iop_1Uto8,unop(Iop_32to1,bind(0))));
sewardj443cd9d2004-07-18 23:06:45 +00001019 if (matchIRExpr(&mi,p_32to1_then_1Uto8,e)) {
1020 IRExpr* expr32 = mi.bindee[0];
sewardj38ff3d82004-07-26 23:27:08 +00001021 HReg dst = newVRegI(env);
sewardj443cd9d2004-07-18 23:06:45 +00001022 HReg src = iselIntExpr_R(env, expr32);
sewardjd08f2d72004-12-01 23:19:36 +00001023 addInstr(env, mk_iMOVsd_RR(src,dst) );
sewardj443cd9d2004-07-18 23:06:45 +00001024 addInstr(env, X86Instr_Alu32R(Xalu_AND,
1025 X86RMI_Imm(1), dst));
1026 return dst;
1027 }
1028
sewardjd18d1bf2004-08-25 12:49:22 +00001029 /* 16Uto32(LDle(expr32)) */
1030 {
1031 DECLARE_PATTERN(p_LDle16_then_16Uto32);
1032 DEFINE_PATTERN(p_LDle16_then_16Uto32,
1033 unop(Iop_16Uto32,IRExpr_LDle(Ity_I16,bind(0))) );
1034 if (matchIRExpr(&mi,p_LDle16_then_16Uto32,e)) {
1035 HReg dst = newVRegI(env);
1036 X86AMode* amode = iselIntExpr_AMode ( env, mi.bindee[0] );
1037 addInstr(env, X86Instr_LoadEX(2,False,amode,dst));
1038 return dst;
1039 }
1040 }
1041
sewardj4042c7e2004-07-18 01:28:30 +00001042 switch (e->Iex.Unop.op) {
sewardj47341042004-09-19 11:55:46 +00001043 case Iop_8Uto16:
sewardj443cd9d2004-07-18 23:06:45 +00001044 case Iop_8Uto32:
1045 case Iop_16Uto32: {
sewardj4042c7e2004-07-18 01:28:30 +00001046 HReg dst = newVRegI(env);
1047 HReg src = iselIntExpr_R(env, e->Iex.Unop.arg);
sewardj47341042004-09-19 11:55:46 +00001048 UInt mask = e->Iex.Unop.op==Iop_16Uto32 ? 0xFFFF : 0xFF;
sewardjd08f2d72004-12-01 23:19:36 +00001049 addInstr(env, mk_iMOVsd_RR(src,dst) );
sewardj4042c7e2004-07-18 01:28:30 +00001050 addInstr(env, X86Instr_Alu32R(Xalu_AND,
sewardj443cd9d2004-07-18 23:06:45 +00001051 X86RMI_Imm(mask), dst));
1052 return dst;
1053 }
sewardj47341042004-09-19 11:55:46 +00001054 case Iop_8Sto16:
sewardjc22a6fd2004-07-29 23:41:47 +00001055 case Iop_8Sto32:
1056 case Iop_16Sto32: {
1057 HReg dst = newVRegI(env);
1058 HReg src = iselIntExpr_R(env, e->Iex.Unop.arg);
sewardj47341042004-09-19 11:55:46 +00001059 UInt amt = e->Iex.Unop.op==Iop_16Sto32 ? 16 : 24;
sewardjd08f2d72004-12-01 23:19:36 +00001060 addInstr(env, mk_iMOVsd_RR(src,dst) );
sewardjc22a6fd2004-07-29 23:41:47 +00001061 addInstr(env, X86Instr_Sh32(Xsh_SHL, amt, X86RM_Reg(dst)));
1062 addInstr(env, X86Instr_Sh32(Xsh_SAR, amt, X86RM_Reg(dst)));
1063 return dst;
1064 }
sewardja2384712004-07-29 14:36:40 +00001065 case Iop_Not8:
1066 case Iop_Not16:
sewardj443cd9d2004-07-18 23:06:45 +00001067 case Iop_Not32: {
1068 HReg dst = newVRegI(env);
1069 HReg src = iselIntExpr_R(env, e->Iex.Unop.arg);
sewardjd08f2d72004-12-01 23:19:36 +00001070 addInstr(env, mk_iMOVsd_RR(src,dst) );
sewardjd4a4d012004-11-08 18:53:52 +00001071 addInstr(env, X86Instr_Unary32(Xun_NOT,X86RM_Reg(dst)));
sewardj4042c7e2004-07-18 01:28:30 +00001072 return dst;
1073 }
sewardj597b71b2004-07-19 02:51:12 +00001074 case Iop_64HIto32: {
1075 HReg rHi, rLo;
sewardjd08f2d72004-12-01 23:19:36 +00001076 iselInt64Expr(&rHi,&rLo, env, e->Iex.Unop.arg);
sewardj597b71b2004-07-19 02:51:12 +00001077 return rHi; /* and abandon rLo .. poor wee thing :-) */
1078 }
sewardj8c7f1ab2004-07-29 20:31:09 +00001079 case Iop_64to32: {
sewardj597b71b2004-07-19 02:51:12 +00001080 HReg rHi, rLo;
sewardjd08f2d72004-12-01 23:19:36 +00001081 iselInt64Expr(&rHi,&rLo, env, e->Iex.Unop.arg);
sewardj597b71b2004-07-19 02:51:12 +00001082 return rLo; /* similar stupid comment to the above ... */
1083 }
sewardjb81f8b32004-07-30 10:17:50 +00001084 case Iop_16HIto8:
sewardj8c7f1ab2004-07-29 20:31:09 +00001085 case Iop_32HIto16: {
sewardjb81f8b32004-07-30 10:17:50 +00001086 HReg dst = newVRegI(env);
1087 HReg src = iselIntExpr_R(env, e->Iex.Unop.arg);
1088 Int shift = e->Iex.Unop.op == Iop_16HIto8 ? 8 : 16;
sewardjd08f2d72004-12-01 23:19:36 +00001089 addInstr(env, mk_iMOVsd_RR(src,dst) );
sewardjb81f8b32004-07-30 10:17:50 +00001090 addInstr(env, X86Instr_Sh32(Xsh_SHR, shift, X86RM_Reg(dst)));
sewardj8c7f1ab2004-07-29 20:31:09 +00001091 return dst;
1092 }
sewardj84ff0652004-08-23 16:16:08 +00001093 case Iop_1Uto32:
sewardjd7cb8532004-08-17 23:59:23 +00001094 case Iop_1Uto8: {
1095 HReg dst = newVRegI(env);
1096 X86CondCode cond = iselCondCode(env, e->Iex.Unop.arg);
1097 addInstr(env, X86Instr_Set32(cond,dst));
1098 return dst;
1099 }
sewardjfd332772004-11-09 16:01:40 +00001100 case Iop_1Sto8:
sewardj218e29f2004-11-07 18:45:15 +00001101 case Iop_1Sto16:
sewardj415d9352004-11-04 15:20:15 +00001102 case Iop_1Sto32: {
1103 /* could do better than this, but for now ... */
1104 HReg dst = newVRegI(env);
1105 X86CondCode cond = iselCondCode(env, e->Iex.Unop.arg);
1106 addInstr(env, X86Instr_Set32(cond,dst));
1107 addInstr(env, X86Instr_Sh32(Xsh_SHL, 31, X86RM_Reg(dst)));
1108 addInstr(env, X86Instr_Sh32(Xsh_SAR, 31, X86RM_Reg(dst)));
1109 return dst;
1110 }
sewardjce646f22004-08-31 23:55:54 +00001111 case Iop_Ctz32: {
1112 /* Count trailing zeroes, implemented by x86 'bsfl' */
1113 HReg dst = newVRegI(env);
1114 HReg src = iselIntExpr_R(env, e->Iex.Unop.arg);
1115 addInstr(env, X86Instr_Bsfr32(True,src,dst));
1116 return dst;
1117 }
1118 case Iop_Clz32: {
1119 /* Count leading zeroes. Do 'bsrl' to establish the index
1120 of the highest set bit, and subtract that value from
1121 31. */
1122 HReg tmp = newVRegI(env);
1123 HReg dst = newVRegI(env);
1124 HReg src = iselIntExpr_R(env, e->Iex.Unop.arg);
1125 addInstr(env, X86Instr_Bsfr32(False,src,tmp));
1126 addInstr(env, X86Instr_Alu32R(Xalu_MOV,
1127 X86RMI_Imm(31), dst));
1128 addInstr(env, X86Instr_Alu32R(Xalu_SUB,
1129 X86RMI_Reg(tmp), dst));
1130 return dst;
1131 }
sewardj89cd0932004-09-08 18:23:25 +00001132
sewardjb81f8b32004-07-30 10:17:50 +00001133 case Iop_16to8:
sewardja2384712004-07-29 14:36:40 +00001134 case Iop_32to8:
1135 case Iop_32to16:
sewardjb81f8b32004-07-30 10:17:50 +00001136 /* These are no-ops. */
sewardja2384712004-07-29 14:36:40 +00001137 return iselIntExpr_R(env, e->Iex.Unop.arg);
1138
sewardj4042c7e2004-07-18 01:28:30 +00001139 default:
1140 break;
1141 }
1142 break;
1143 }
1144
sewardj60f4e3c2004-07-19 01:56:50 +00001145 /* --------- GET --------- */
sewardje8e9d732004-07-16 21:03:45 +00001146 case Iex_Get: {
1147 if (ty == Ity_I32) {
1148 HReg dst = newVRegI(env);
1149 addInstr(env, X86Instr_Alu32R(
1150 Xalu_MOV,
1151 X86RMI_Mem(X86AMode_IR(e->Iex.Get.offset,
1152 hregX86_EBP())),
1153 dst));
1154 return dst;
sewardjc97096c2004-06-30 09:28:04 +00001155 }
sewardj60f4e3c2004-07-19 01:56:50 +00001156 if (ty == Ity_I8 || ty == Ity_I16) {
sewardj4042c7e2004-07-18 01:28:30 +00001157 HReg dst = newVRegI(env);
1158 addInstr(env, X86Instr_LoadEX(
sewardj60f4e3c2004-07-19 01:56:50 +00001159 ty==Ity_I8 ? 1 : 2,
1160 False,
sewardj4042c7e2004-07-18 01:28:30 +00001161 X86AMode_IR(e->Iex.Get.offset,hregX86_EBP()),
1162 dst));
1163 return dst;
1164 }
sewardje8e9d732004-07-16 21:03:45 +00001165 break;
sewardjc97096c2004-06-30 09:28:04 +00001166 }
sewardje8e9d732004-07-16 21:03:45 +00001167
sewardj33124f62004-08-30 17:54:18 +00001168 case Iex_GetI: {
sewardj2d3f77c2004-09-22 23:49:09 +00001169 X86AMode* am
1170 = genGuestArrayOffset(
1171 env, e->Iex.GetI.descr,
sewardjeeac8412004-11-02 00:26:55 +00001172 e->Iex.GetI.ix, e->Iex.GetI.bias );
sewardj33124f62004-08-30 17:54:18 +00001173 HReg dst = newVRegI(env);
1174 if (ty == Ity_I8) {
sewardj2d3f77c2004-09-22 23:49:09 +00001175 addInstr(env, X86Instr_LoadEX( 1, False, am, dst ));
sewardj33124f62004-08-30 17:54:18 +00001176 return dst;
1177 }
sewardj2d3f77c2004-09-22 23:49:09 +00001178 break;
sewardj33124f62004-08-30 17:54:18 +00001179 }
1180
sewardj60f4e3c2004-07-19 01:56:50 +00001181 /* --------- CCALL --------- */
sewardje8e9d732004-07-16 21:03:45 +00001182 case Iex_CCall: {
sewardjd18d1bf2004-08-25 12:49:22 +00001183 HReg dst = newVRegI(env);
sewardje8e9d732004-07-16 21:03:45 +00001184 vassert(ty == Ity_I32);
sewardjc4be80c2004-09-10 16:17:45 +00001185
1186 /* be very restrictive for now. Only 32/64-bit ints allowed
1187 for args, and 32 bits for return type. */
sewardj4042c7e2004-07-18 01:28:30 +00001188 if (e->Iex.CCall.retty != Ity_I32)
sewardjd18d1bf2004-08-25 12:49:22 +00001189 goto irreducible;
sewardjc4be80c2004-09-10 16:17:45 +00001190
sewardj77352542004-10-30 20:39:01 +00001191 /* Marshal args, do the call, clear stack. */
sewardj4b861de2004-11-03 15:24:42 +00001192 doHelperCall( env, False, NULL, e->Iex.CCall.cee, e->Iex.CCall.args );
sewardj17442fe2004-09-20 14:54:28 +00001193
sewardjd08f2d72004-12-01 23:19:36 +00001194 addInstr(env, mk_iMOVsd_RR(hregX86_EAX(), dst));
sewardjd18d1bf2004-08-25 12:49:22 +00001195 return dst;
sewardje8e9d732004-07-16 21:03:45 +00001196 }
1197
sewardj60f4e3c2004-07-19 01:56:50 +00001198 /* --------- LITERAL --------- */
sewardje8e9d732004-07-16 21:03:45 +00001199 /* 32/16/8-bit literals */
1200 case Iex_Const: {
sewardj4042c7e2004-07-18 01:28:30 +00001201 X86RMI* rmi = iselIntExpr_RMI ( env, e );
1202 HReg r = newVRegI(env);
1203 addInstr(env, X86Instr_Alu32R(Xalu_MOV, rmi, r));
sewardje8e9d732004-07-16 21:03:45 +00001204 return r;
1205 }
sewardjc97096c2004-06-30 09:28:04 +00001206
sewardj60f4e3c2004-07-19 01:56:50 +00001207 /* --------- MULTIPLEX --------- */
sewardj4042c7e2004-07-18 01:28:30 +00001208 case Iex_Mux0X: {
sewardjc744e872004-08-26 11:24:39 +00001209 if ((ty == Ity_I32 || ty == Ity_I16 || ty == Ity_I8)
sewardj4042c7e2004-07-18 01:28:30 +00001210 && typeOfIRExpr(env->type_env,e->Iex.Mux0X.cond) == Ity_I8) {
sewardj2e56f9f2004-07-24 01:24:38 +00001211 HReg r8;
sewardj38ff3d82004-07-26 23:27:08 +00001212 HReg rX = iselIntExpr_R(env, e->Iex.Mux0X.exprX);
1213 X86RM* r0 = iselIntExpr_RM(env, e->Iex.Mux0X.expr0);
1214 HReg dst = newVRegI(env);
sewardjd08f2d72004-12-01 23:19:36 +00001215 addInstr(env, mk_iMOVsd_RR(rX,dst));
sewardj38ff3d82004-07-26 23:27:08 +00001216 r8 = iselIntExpr_R(env, e->Iex.Mux0X.cond);
1217 addInstr(env, X86Instr_Test32(X86RI_Imm(0xFF), X86RM_Reg(r8)));
1218 addInstr(env, X86Instr_CMov32(Xcc_Z,r0,dst));
1219 return dst;
sewardj4042c7e2004-07-18 01:28:30 +00001220 }
1221 break;
1222 }
1223
sewardjc97096c2004-06-30 09:28:04 +00001224 default:
1225 break;
1226 } /* switch (e->tag) */
1227
1228 /* We get here if no pattern matched. */
sewardje8e9d732004-07-16 21:03:45 +00001229 irreducible:
sewardj35421a32004-07-05 13:12:34 +00001230 ppIRExpr(e);
sewardjd9c2b792004-07-08 01:44:38 +00001231 vpanic("iselIntExpr_R: cannot reduce tree");
sewardjc97096c2004-06-30 09:28:04 +00001232}
1233
1234
sewardj66f2f792004-06-30 16:37:16 +00001235/*---------------------------------------------------------*/
1236/*--- ISEL: Integer expression auxiliaries ---*/
1237/*---------------------------------------------------------*/
1238
sewardjd18d1bf2004-08-25 12:49:22 +00001239/* --------------------- AMODEs --------------------- */
sewardj60f4e3c2004-07-19 01:56:50 +00001240
sewardj66f2f792004-06-30 16:37:16 +00001241/* Return an AMode which computes the value of the specified
1242 expression, possibly also adding insns to the code list as a
sewardj4042c7e2004-07-18 01:28:30 +00001243 result. The expression may only be a 32-bit one.
sewardjc97096c2004-06-30 09:28:04 +00001244*/
sewardjd18d1bf2004-08-25 12:49:22 +00001245
1246static Bool sane_AMode ( X86AMode* am )
1247{
1248 switch (am->tag) {
1249 case Xam_IR:
sewardj4a31b262004-12-01 02:24:44 +00001250 return hregClass(am->Xam.IR.reg) == HRcInt32
sewardjd18d1bf2004-08-25 12:49:22 +00001251 && (hregIsVirtual(am->Xam.IR.reg)
1252 || am->Xam.IR.reg == hregX86_EBP());
1253 case Xam_IRRS:
sewardj4a31b262004-12-01 02:24:44 +00001254 return hregClass(am->Xam.IRRS.base) == HRcInt32
sewardjd18d1bf2004-08-25 12:49:22 +00001255 && hregIsVirtual(am->Xam.IRRS.base)
sewardj4a31b262004-12-01 02:24:44 +00001256 && hregClass(am->Xam.IRRS.index) == HRcInt32
sewardjd18d1bf2004-08-25 12:49:22 +00001257 && hregIsVirtual(am->Xam.IRRS.index);
1258 default:
1259 vpanic("sane_AMode: unknown x86 amode tag");
1260 }
1261}
1262
sewardj66f2f792004-06-30 16:37:16 +00001263static X86AMode* iselIntExpr_AMode ( ISelEnv* env, IRExpr* e )
sewardjc97096c2004-06-30 09:28:04 +00001264{
sewardjd18d1bf2004-08-25 12:49:22 +00001265 X86AMode* am = iselIntExpr_AMode_wrk(env, e);
1266 vassert(sane_AMode(am));
1267 return am;
1268}
1269
1270/* DO NOT CALL THIS DIRECTLY ! */
1271static X86AMode* iselIntExpr_AMode_wrk ( ISelEnv* env, IRExpr* e )
1272{
sewardj4042c7e2004-07-18 01:28:30 +00001273 IRType ty = typeOfIRExpr(env->type_env,e);
1274 vassert(ty == Ity_I32);
sewardjc97096c2004-06-30 09:28:04 +00001275
1276 /* Add32(expr1, Shl32(expr2, imm)) */
1277 if (e->tag == Iex_Binop
1278 && e->Iex.Binop.op == Iop_Add32
1279 && e->Iex.Binop.arg2->tag == Iex_Binop
1280 && e->Iex.Binop.arg2->Iex.Binop.op == Iop_Shl32
1281 && e->Iex.Binop.arg2->Iex.Binop.arg2->tag == Iex_Const
sewardjd18d1bf2004-08-25 12:49:22 +00001282 && e->Iex.Binop.arg2->Iex.Binop.arg2->Iex.Const.con->tag == Ico_U8) {
1283 UInt shift = e->Iex.Binop.arg2->Iex.Binop.arg2->Iex.Const.con->Ico.U8;
1284 if (shift == 1 || shift == 2 || shift == 3) {
sewardj66f2f792004-06-30 16:37:16 +00001285 HReg r1 = iselIntExpr_R(env, e->Iex.Binop.arg1);
1286 HReg r2 = iselIntExpr_R(env, e->Iex.Binop.arg2->Iex.Binop.arg1 );
sewardjc97096c2004-06-30 09:28:04 +00001287 return X86AMode_IRRS(0, r1, r2, shift);
1288 }
1289 }
1290
1291 /* Add32(expr,i) */
1292 if (e->tag == Iex_Binop
1293 && e->Iex.Binop.op == Iop_Add32
1294 && e->Iex.Binop.arg2->tag == Iex_Const
1295 && e->Iex.Binop.arg2->Iex.Const.con->tag == Ico_U32) {
sewardj66f2f792004-06-30 16:37:16 +00001296 HReg r1 = iselIntExpr_R(env, e->Iex.Binop.arg1);
sewardjd9c2b792004-07-08 01:44:38 +00001297 return X86AMode_IR(e->Iex.Binop.arg2->Iex.Const.con->Ico.U32, r1);
sewardjc97096c2004-06-30 09:28:04 +00001298 }
1299
1300 /* Doesn't match anything in particular. Generate it into
1301 a register and use that. */
1302 {
sewardj66f2f792004-06-30 16:37:16 +00001303 HReg r1 = iselIntExpr_R(env, e);
sewardjd9c2b792004-07-08 01:44:38 +00001304 return X86AMode_IR(0, r1);
sewardjc97096c2004-06-30 09:28:04 +00001305 }
1306}
1307
1308
sewardjd18d1bf2004-08-25 12:49:22 +00001309/* --------------------- RMIs --------------------- */
sewardj60f4e3c2004-07-19 01:56:50 +00001310
sewardj4042c7e2004-07-18 01:28:30 +00001311/* Similarly, calculate an expression into an X86RMI operand. As with
1312 iselIntExpr_R, the expression can have type 32, 16 or 8 bits. */
sewardj66f2f792004-06-30 16:37:16 +00001313
1314static X86RMI* iselIntExpr_RMI ( ISelEnv* env, IRExpr* e )
1315{
sewardjd18d1bf2004-08-25 12:49:22 +00001316 X86RMI* rmi = iselIntExpr_RMI_wrk(env, e);
1317 /* sanity checks ... */
1318 switch (rmi->tag) {
1319 case Xrmi_Imm:
1320 return rmi;
1321 case Xrmi_Reg:
sewardj4a31b262004-12-01 02:24:44 +00001322 vassert(hregClass(rmi->Xrmi.Reg.reg) == HRcInt32);
sewardjd18d1bf2004-08-25 12:49:22 +00001323 vassert(hregIsVirtual(rmi->Xrmi.Reg.reg));
1324 return rmi;
1325 case Xrmi_Mem:
1326 vassert(sane_AMode(rmi->Xrmi.Mem.am));
1327 return rmi;
1328 default:
1329 vpanic("iselIntExpr_RMI: unknown x86 RMI tag");
1330 }
1331}
1332
1333/* DO NOT CALL THIS DIRECTLY ! */
1334static X86RMI* iselIntExpr_RMI_wrk ( ISelEnv* env, IRExpr* e )
1335{
sewardj4042c7e2004-07-18 01:28:30 +00001336 IRType ty = typeOfIRExpr(env->type_env,e);
1337 vassert(ty == Ity_I32 || ty == Ity_I16 || ty == Ity_I8);
sewardj66f2f792004-06-30 16:37:16 +00001338
1339 /* special case: immediate */
sewardj4042c7e2004-07-18 01:28:30 +00001340 if (e->tag == Iex_Const) {
1341 UInt u;
1342 switch (e->Iex.Const.con->tag) {
1343 case Ico_U32: u = e->Iex.Const.con->Ico.U32; break;
1344 case Ico_U16: u = 0xFFFF & (e->Iex.Const.con->Ico.U16); break;
1345 case Ico_U8: u = 0xFF & (e->Iex.Const.con->Ico.U8); break;
1346 default: vpanic("iselIntExpr_RMI.Iex_Const(x86h)");
1347 }
1348 return X86RMI_Imm(u);
sewardj66f2f792004-06-30 16:37:16 +00001349 }
1350
sewardje8e9d732004-07-16 21:03:45 +00001351 /* special case: 32-bit GET */
sewardj4042c7e2004-07-18 01:28:30 +00001352 if (e->tag == Iex_Get && ty == Ity_I32) {
sewardje8e9d732004-07-16 21:03:45 +00001353 return X86RMI_Mem(X86AMode_IR(e->Iex.Get.offset,
1354 hregX86_EBP()));
1355 }
1356
sewardj66f2f792004-06-30 16:37:16 +00001357 /* special case: load from memory */
1358
1359 /* default case: calculate into a register and return that */
1360 {
1361 HReg r = iselIntExpr_R ( env, e );
1362 return X86RMI_Reg(r);
1363 }
1364}
1365
1366
sewardjd18d1bf2004-08-25 12:49:22 +00001367/* --------------------- RIs --------------------- */
sewardj60f4e3c2004-07-19 01:56:50 +00001368
sewardj4042c7e2004-07-18 01:28:30 +00001369/* Calculate an expression into an X86RI operand. As with
1370 iselIntExpr_R, the expression can have type 32, 16 or 8 bits. */
sewardj66f2f792004-06-30 16:37:16 +00001371
1372static X86RI* iselIntExpr_RI ( ISelEnv* env, IRExpr* e )
1373{
sewardjd18d1bf2004-08-25 12:49:22 +00001374 X86RI* ri = iselIntExpr_RI_wrk(env, e);
1375 /* sanity checks ... */
1376 switch (ri->tag) {
1377 case Xri_Imm:
1378 return ri;
1379 case Xrmi_Reg:
sewardj4a31b262004-12-01 02:24:44 +00001380 vassert(hregClass(ri->Xri.Reg.reg) == HRcInt32);
sewardjd18d1bf2004-08-25 12:49:22 +00001381 vassert(hregIsVirtual(ri->Xri.Reg.reg));
1382 return ri;
1383 default:
1384 vpanic("iselIntExpr_RI: unknown x86 RI tag");
1385 }
1386}
1387
1388/* DO NOT CALL THIS DIRECTLY ! */
1389static X86RI* iselIntExpr_RI_wrk ( ISelEnv* env, IRExpr* e )
1390{
sewardj4042c7e2004-07-18 01:28:30 +00001391 IRType ty = typeOfIRExpr(env->type_env,e);
1392 vassert(ty == Ity_I32 || ty == Ity_I16 || ty == Ity_I8);
sewardj66f2f792004-06-30 16:37:16 +00001393
1394 /* special case: immediate */
sewardj4042c7e2004-07-18 01:28:30 +00001395 if (e->tag == Iex_Const) {
1396 UInt u;
1397 switch (e->Iex.Const.con->tag) {
1398 case Ico_U32: u = e->Iex.Const.con->Ico.U32; break;
1399 case Ico_U16: u = 0xFFFF & (e->Iex.Const.con->Ico.U16); break;
1400 case Ico_U8: u = 0xFF & (e->Iex.Const.con->Ico.U8); break;
1401 default: vpanic("iselIntExpr_RMI.Iex_Const(x86h)");
1402 }
1403 return X86RI_Imm(u);
sewardj66f2f792004-06-30 16:37:16 +00001404 }
1405
1406 /* default case: calculate into a register and return that */
1407 {
1408 HReg r = iselIntExpr_R ( env, e );
1409 return X86RI_Reg(r);
1410 }
1411}
1412
1413
sewardjd18d1bf2004-08-25 12:49:22 +00001414/* --------------------- RMs --------------------- */
sewardj60f4e3c2004-07-19 01:56:50 +00001415
sewardj4042c7e2004-07-18 01:28:30 +00001416/* Similarly, calculate an expression into an X86RM operand. As with
1417 iselIntExpr_R, the expression can have type 32, 16 or 8 bits. */
1418
1419static X86RM* iselIntExpr_RM ( ISelEnv* env, IRExpr* e )
1420{
sewardjd18d1bf2004-08-25 12:49:22 +00001421 X86RM* rm = iselIntExpr_RM_wrk(env, e);
1422 /* sanity checks ... */
1423 switch (rm->tag) {
1424 case Xrm_Reg:
sewardj4a31b262004-12-01 02:24:44 +00001425 vassert(hregClass(rm->Xrm.Reg.reg) == HRcInt32);
sewardjd18d1bf2004-08-25 12:49:22 +00001426 vassert(hregIsVirtual(rm->Xrm.Reg.reg));
1427 return rm;
1428 case Xrm_Mem:
1429 vassert(sane_AMode(rm->Xrm.Mem.am));
1430 return rm;
1431 default:
1432 vpanic("iselIntExpr_RM: unknown x86 RM tag");
1433 }
1434}
1435
1436/* DO NOT CALL THIS DIRECTLY ! */
1437static X86RM* iselIntExpr_RM_wrk ( ISelEnv* env, IRExpr* e )
1438{
sewardj4042c7e2004-07-18 01:28:30 +00001439 IRType ty = typeOfIRExpr(env->type_env,e);
1440 vassert(ty == Ity_I32 || ty == Ity_I16 || ty == Ity_I8);
1441
1442 /* special case: 32-bit GET */
1443 if (e->tag == Iex_Get && ty == Ity_I32) {
1444 return X86RM_Mem(X86AMode_IR(e->Iex.Get.offset,
1445 hregX86_EBP()));
1446 }
1447
1448 /* special case: load from memory */
1449
1450 /* default case: calculate into a register and return that */
1451 {
1452 HReg r = iselIntExpr_R ( env, e );
1453 return X86RM_Reg(r);
1454 }
1455}
1456
1457
sewardjd18d1bf2004-08-25 12:49:22 +00001458/* --------------------- CONDCODE --------------------- */
sewardj60f4e3c2004-07-19 01:56:50 +00001459
sewardj443cd9d2004-07-18 23:06:45 +00001460/* Generate code to evaluated a bit-typed expression, returning the
1461 condition code which would correspond when the expression would
1462 notionally have returned 1. */
1463
1464static X86CondCode iselCondCode ( ISelEnv* env, IRExpr* e )
1465{
sewardjd18d1bf2004-08-25 12:49:22 +00001466 /* Uh, there's nothing we can sanity check here, unfortunately. */
1467 return iselCondCode_wrk(env,e);
1468}
1469
1470/* DO NOT CALL THIS DIRECTLY ! */
1471static X86CondCode iselCondCode_wrk ( ISelEnv* env, IRExpr* e )
1472{
sewardj443cd9d2004-07-18 23:06:45 +00001473 MatchInfo mi;
1474 DECLARE_PATTERN(p_32to1);
sewardj8f3debf2004-09-08 23:42:23 +00001475 //DECLARE_PATTERN(p_eq32_literal);
1476 //DECLARE_PATTERN(p_ne32_zero);
sewardj84ff0652004-08-23 16:16:08 +00001477 DECLARE_PATTERN(p_1Uto32_then_32to1);
sewardj443cd9d2004-07-18 23:06:45 +00001478
1479 vassert(e);
sewardjba999312004-11-15 15:21:17 +00001480 vassert(typeOfIRExpr(env->type_env,e) == Ity_I1);
sewardj443cd9d2004-07-18 23:06:45 +00001481
sewardj0dc3ff92004-10-16 11:31:31 +00001482 /* Constant 1:Bit */
sewardjba999312004-11-15 15:21:17 +00001483 if (e->tag == Iex_Const && e->Iex.Const.con->Ico.U1 == True) {
sewardj8fc93742004-11-22 11:29:33 +00001484 HReg r;
sewardjba999312004-11-15 15:21:17 +00001485 vassert(e->Iex.Const.con->tag == Ico_U1);
sewardj8fc93742004-11-22 11:29:33 +00001486 r = newVRegI(env);
sewardj0dc3ff92004-10-16 11:31:31 +00001487 addInstr(env, X86Instr_Alu32R(Xalu_MOV,X86RMI_Imm(0),r));
1488 addInstr(env, X86Instr_Alu32R(Xalu_XOR,X86RMI_Reg(r),r));
1489 return Xcc_Z;
1490 }
1491
sewardj6e797c52004-10-13 15:20:17 +00001492 /* Not1(...) */
1493 if (e->tag == Iex_Unop && e->Iex.Unop.op == Iop_Not1) {
1494 /* Generate code for the arg, and negate the test condition */
1495 return 1 ^ iselCondCode(env, e->Iex.Unop.arg);
1496 }
1497
sewardj84ff0652004-08-23 16:16:08 +00001498 /* 32to1(1Uto32(expr1)) -- the casts are pointless, ignore them */
1499 DEFINE_PATTERN(p_1Uto32_then_32to1,
1500 unop(Iop_32to1,unop(Iop_1Uto32,bind(0))));
1501 if (matchIRExpr(&mi,p_1Uto32_then_32to1,e)) {
1502 IRExpr* expr1 = mi.bindee[0];
1503 return iselCondCode(env, expr1);
1504 }
1505
sewardj443cd9d2004-07-18 23:06:45 +00001506 /* pattern: 32to1(expr32) */
1507 DEFINE_PATTERN(p_32to1,
1508 unop(Iop_32to1,bind(0))
1509 );
1510 if (matchIRExpr(&mi,p_32to1,e)) {
sewardj09cc2fe2004-08-18 00:28:48 +00001511 X86RM* rm = iselIntExpr_RM(env, mi.bindee[0]);
1512 addInstr(env, X86Instr_Test32(X86RI_Imm(1),rm));
sewardj443cd9d2004-07-18 23:06:45 +00001513 return Xcc_NZ;
1514 }
1515
sewardjb9c5cf62004-08-24 15:10:38 +00001516 /* CmpEQ8 / CmpNE8 */
sewardj84ff0652004-08-23 16:16:08 +00001517 if (e->tag == Iex_Binop
sewardjb9c5cf62004-08-24 15:10:38 +00001518 && (e->Iex.Binop.op == Iop_CmpEQ8
1519 || e->Iex.Binop.op == Iop_CmpNE8)) {
1520 HReg r1 = iselIntExpr_R(env, e->Iex.Binop.arg1);
1521 X86RMI* rmi2 = iselIntExpr_RMI(env, e->Iex.Binop.arg2);
1522 HReg r = newVRegI(env);
sewardjd08f2d72004-12-01 23:19:36 +00001523 addInstr(env, mk_iMOVsd_RR(r1,r));
sewardjb9c5cf62004-08-24 15:10:38 +00001524 addInstr(env, X86Instr_Alu32R(Xalu_XOR,rmi2,r));
1525 addInstr(env, X86Instr_Alu32R(Xalu_AND,X86RMI_Imm(0xFF),r));
1526 switch (e->Iex.Binop.op) {
1527 case Iop_CmpEQ8: return Xcc_Z;
1528 case Iop_CmpNE8: return Xcc_NZ;
1529 default: vpanic("iselCondCode(x86): CmpXX8");
1530 }
1531 }
1532
1533 /* CmpEQ16 / CmpNE16 */
1534 if (e->tag == Iex_Binop
1535 && (e->Iex.Binop.op == Iop_CmpEQ16
1536 || e->Iex.Binop.op == Iop_CmpNE16)) {
1537 HReg r1 = iselIntExpr_R(env, e->Iex.Binop.arg1);
1538 X86RMI* rmi2 = iselIntExpr_RMI(env, e->Iex.Binop.arg2);
1539 HReg r = newVRegI(env);
sewardjd08f2d72004-12-01 23:19:36 +00001540 addInstr(env, mk_iMOVsd_RR(r1,r));
sewardjb9c5cf62004-08-24 15:10:38 +00001541 addInstr(env, X86Instr_Alu32R(Xalu_XOR,rmi2,r));
1542 addInstr(env, X86Instr_Alu32R(Xalu_AND,X86RMI_Imm(0xFFFF),r));
1543 switch (e->Iex.Binop.op) {
1544 case Iop_CmpEQ16: return Xcc_Z;
1545 case Iop_CmpNE16: return Xcc_NZ;
sewardjb5874aa2004-11-04 16:57:50 +00001546 default: vpanic("iselCondCode(x86): CmpXX16");
sewardjb9c5cf62004-08-24 15:10:38 +00001547 }
1548 }
1549
sewardj6f33f752004-11-11 02:17:53 +00001550 /* CmpNE32(1Sto32(b), 0) ==> b */
1551 {
1552 DECLARE_PATTERN(p_CmpNE32_1Sto32);
1553 DEFINE_PATTERN(
1554 p_CmpNE32_1Sto32,
1555 binop(Iop_CmpNE32, unop(Iop_1Sto32,bind(0)), mkU32(0)));
1556 if (matchIRExpr(&mi, p_CmpNE32_1Sto32, e)) {
1557 return iselCondCode(env, mi.bindee[0]);
1558 }
1559 }
1560
sewardjb9c5cf62004-08-24 15:10:38 +00001561 /* Cmp*32*(x,y) */
1562 if (e->tag == Iex_Binop
1563 && (e->Iex.Binop.op == Iop_CmpEQ32
1564 || e->Iex.Binop.op == Iop_CmpNE32
1565 || e->Iex.Binop.op == Iop_CmpLT32S
sewardj84ff0652004-08-23 16:16:08 +00001566 || e->Iex.Binop.op == Iop_CmpLT32U
1567 || e->Iex.Binop.op == Iop_CmpLE32S
1568 || e->Iex.Binop.op == Iop_CmpLE32U)) {
sewardjb9c5cf62004-08-24 15:10:38 +00001569 HReg r1 = iselIntExpr_R(env, e->Iex.Binop.arg1);
sewardj84ff0652004-08-23 16:16:08 +00001570 X86RMI* rmi2 = iselIntExpr_RMI(env, e->Iex.Binop.arg2);
1571 addInstr(env, X86Instr_Alu32R(Xalu_CMP,rmi2,r1));
1572 switch (e->Iex.Binop.op) {
sewardjb9c5cf62004-08-24 15:10:38 +00001573 case Iop_CmpEQ32: return Xcc_Z;
1574 case Iop_CmpNE32: return Xcc_NZ;
sewardj84ff0652004-08-23 16:16:08 +00001575 case Iop_CmpLT32S: return Xcc_L;
1576 case Iop_CmpLT32U: return Xcc_B;
1577 case Iop_CmpLE32S: return Xcc_LE;
1578 case Iop_CmpLE32U: return Xcc_BE;
sewardjb9c5cf62004-08-24 15:10:38 +00001579 default: vpanic("iselCondCode(x86): CmpXX32");
sewardj84ff0652004-08-23 16:16:08 +00001580 }
1581 }
1582
sewardj6f33f752004-11-11 02:17:53 +00001583 /* CmpNE64(1Sto64(b), 0) ==> b */
1584 {
1585 DECLARE_PATTERN(p_CmpNE64_1Sto64);
1586 DEFINE_PATTERN(
1587 p_CmpNE64_1Sto64,
1588 binop(Iop_CmpNE64, unop(Iop_1Sto64,bind(0)), mkU64(0)));
1589 if (matchIRExpr(&mi, p_CmpNE64_1Sto64, e)) {
1590 return iselCondCode(env, mi.bindee[0]);
1591 }
1592 }
1593
sewardjb5874aa2004-11-04 16:57:50 +00001594 /* CmpNE64 */
1595 if (e->tag == Iex_Binop
1596 && e->Iex.Binop.op == Iop_CmpNE64) {
1597 HReg hi1, hi2, lo1, lo2;
1598 HReg tHi = newVRegI(env);
1599 HReg tLo = newVRegI(env);
sewardjd08f2d72004-12-01 23:19:36 +00001600 iselInt64Expr( &hi1, &lo1, env, e->Iex.Binop.arg1 );
1601 iselInt64Expr( &hi2, &lo2, env, e->Iex.Binop.arg2 );
1602 addInstr(env, mk_iMOVsd_RR(hi1, tHi));
sewardjb5874aa2004-11-04 16:57:50 +00001603 addInstr(env, X86Instr_Alu32R(Xalu_XOR,X86RMI_Reg(hi2), tHi));
sewardjd08f2d72004-12-01 23:19:36 +00001604 addInstr(env, mk_iMOVsd_RR(lo1, tLo));
sewardjb5874aa2004-11-04 16:57:50 +00001605 addInstr(env, X86Instr_Alu32R(Xalu_XOR,X86RMI_Reg(lo2), tLo));
1606 addInstr(env, X86Instr_Alu32R(Xalu_OR,X86RMI_Reg(tHi), tLo));
1607 switch (e->Iex.Binop.op) {
1608 case Iop_CmpNE64: return Xcc_NZ;
1609 default: vpanic("iselCondCode(x86): CmpXX64");
1610 }
1611 }
1612
sewardjd7cb8532004-08-17 23:59:23 +00001613 /* var */
1614 if (e->tag == Iex_Tmp) {
1615 HReg r32 = lookupIRTemp(env, e->Iex.Tmp.tmp);
1616 HReg dst = newVRegI(env);
sewardjd08f2d72004-12-01 23:19:36 +00001617 addInstr(env, mk_iMOVsd_RR(r32,dst));
sewardjd7cb8532004-08-17 23:59:23 +00001618 addInstr(env, X86Instr_Alu32R(Xalu_AND,X86RMI_Imm(1),dst));
1619 return Xcc_NZ;
1620 }
1621
sewardj443cd9d2004-07-18 23:06:45 +00001622 ppIRExpr(e);
1623 vpanic("iselCondCode");
1624}
1625
1626
sewardj597b71b2004-07-19 02:51:12 +00001627/*---------------------------------------------------------*/
1628/*--- ISEL: Integer expressions (64 bit) ---*/
1629/*---------------------------------------------------------*/
1630
1631/* Compute a 64-bit value into a register pair, which is returned as
1632 the first two parameters. As with iselIntExpr_R, these may be
1633 either real or virtual regs; in any case they must not be changed
1634 by subsequent code emitted by the caller. */
1635
sewardjd08f2d72004-12-01 23:19:36 +00001636static void iselInt64Expr ( HReg* rHi, HReg* rLo, ISelEnv* env, IRExpr* e )
sewardj597b71b2004-07-19 02:51:12 +00001637{
sewardjd08f2d72004-12-01 23:19:36 +00001638 iselInt64Expr_wrk(rHi, rLo, env, e);
sewardjd18d1bf2004-08-25 12:49:22 +00001639# if 0
1640 vex_printf("\n"); ppIRExpr(e); vex_printf("\n");
1641# endif
sewardj4a31b262004-12-01 02:24:44 +00001642 vassert(hregClass(*rHi) == HRcInt32);
sewardjd18d1bf2004-08-25 12:49:22 +00001643 vassert(hregIsVirtual(*rHi));
sewardj4a31b262004-12-01 02:24:44 +00001644 vassert(hregClass(*rLo) == HRcInt32);
sewardjd18d1bf2004-08-25 12:49:22 +00001645 vassert(hregIsVirtual(*rLo));
1646}
1647
1648/* DO NOT CALL THIS DIRECTLY ! */
sewardjd08f2d72004-12-01 23:19:36 +00001649static void iselInt64Expr_wrk ( HReg* rHi, HReg* rLo, ISelEnv* env, IRExpr* e )
sewardjd18d1bf2004-08-25 12:49:22 +00001650{
sewardj597b71b2004-07-19 02:51:12 +00001651 vassert(e);
1652 vassert(typeOfIRExpr(env->type_env,e) == Ity_I64);
1653
sewardjc09278c2004-08-19 17:15:49 +00001654 if (e->tag == Iex_Const) {
1655 ULong w64 = e->Iex.Const.con->Ico.U64;
1656 UInt wHi = ((UInt)(w64 >> 32)) & 0xFFFFFFFF;
1657 UInt wLo = ((UInt)w64) & 0xFFFFFFFF;
1658 HReg tLo = newVRegI(env);
1659 HReg tHi = newVRegI(env);
1660 vassert(e->Iex.Const.con->tag == Ico_U64);
1661 addInstr(env, X86Instr_Alu32R(Xalu_MOV, X86RMI_Imm(wHi), tHi));
1662 addInstr(env, X86Instr_Alu32R(Xalu_MOV, X86RMI_Imm(wLo), tLo));
1663 *rHi = tHi;
1664 *rLo = tLo;
1665 return;
1666 }
1667
sewardj597b71b2004-07-19 02:51:12 +00001668 /* read 64-bit IRTemp */
1669 if (e->tag == Iex_Tmp) {
1670 lookupIRTemp64( rHi, rLo, env, e->Iex.Tmp.tmp);
1671 return;
1672 }
1673
sewardjbdc7d212004-09-09 02:46:40 +00001674 /* 64-bit load */
1675 if (e->tag == Iex_LDle) {
sewardjd08f2d72004-12-01 23:19:36 +00001676 HReg tLo, tHi;
1677 X86AMode *am0, *am4;
sewardjbdc7d212004-09-09 02:46:40 +00001678 vassert(e->Iex.LDle.ty == Ity_I64);
sewardj8fc93742004-11-22 11:29:33 +00001679 tLo = newVRegI(env);
1680 tHi = newVRegI(env);
sewardjd08f2d72004-12-01 23:19:36 +00001681 am0 = iselIntExpr_AMode(env, e->Iex.LDle.addr);
1682 am4 = advance4(am0);
1683 addInstr(env, X86Instr_Alu32R( Xalu_MOV, X86RMI_Mem(am0), tLo ));
1684 addInstr(env, X86Instr_Alu32R( Xalu_MOV, X86RMI_Mem(am4), tHi ));
sewardjbdc7d212004-09-09 02:46:40 +00001685 *rHi = tHi;
1686 *rLo = tLo;
1687 return;
1688 }
1689
sewardj464efa42004-11-19 22:17:29 +00001690 /* 64-bit GET */
1691 if (e->tag == Iex_Get) {
1692 X86AMode* am = X86AMode_IR(e->Iex.Get.offset, hregX86_EBP());
1693 X86AMode* am4 = advance4(am);
1694 HReg tLo = newVRegI(env);
1695 HReg tHi = newVRegI(env);
1696 addInstr(env, X86Instr_Alu32R( Xalu_MOV, X86RMI_Mem(am), tLo ));
1697 addInstr(env, X86Instr_Alu32R( Xalu_MOV, X86RMI_Mem(am4), tHi ));
1698 *rHi = tHi;
1699 *rLo = tLo;
1700 return;
1701 }
1702
sewardj218e29f2004-11-07 18:45:15 +00001703 /* 64-bit GETI */
1704 if (e->tag == Iex_GetI) {
1705 X86AMode* am
1706 = genGuestArrayOffset( env, e->Iex.GetI.descr,
1707 e->Iex.GetI.ix, e->Iex.GetI.bias );
1708 X86AMode* am4 = advance4(am);
1709 HReg tLo = newVRegI(env);
1710 HReg tHi = newVRegI(env);
1711 addInstr(env, X86Instr_Alu32R( Xalu_MOV, X86RMI_Mem(am), tLo ));
1712 addInstr(env, X86Instr_Alu32R( Xalu_MOV, X86RMI_Mem(am4), tHi ));
1713 *rHi = tHi;
1714 *rLo = tLo;
1715 return;
1716 }
1717
1718 /* 64-bit Mux0X */
1719 if (e->tag == Iex_Mux0X) {
1720 HReg e0Lo, e0Hi, eXLo, eXHi, r8;
1721 HReg tLo = newVRegI(env);
1722 HReg tHi = newVRegI(env);
sewardjd08f2d72004-12-01 23:19:36 +00001723 iselInt64Expr(&e0Hi, &e0Lo, env, e->Iex.Mux0X.expr0);
1724 iselInt64Expr(&eXHi, &eXLo, env, e->Iex.Mux0X.exprX);
1725 addInstr(env, mk_iMOVsd_RR(eXHi, tHi));
1726 addInstr(env, mk_iMOVsd_RR(eXLo, tLo));
sewardj218e29f2004-11-07 18:45:15 +00001727 r8 = iselIntExpr_R(env, e->Iex.Mux0X.cond);
1728 addInstr(env, X86Instr_Test32(X86RI_Imm(0xFF), X86RM_Reg(r8)));
1729 /* This assumes the first cmov32 doesn't trash the condition
1730 codes, so they are still available for the second cmov32 */
1731 addInstr(env, X86Instr_CMov32(Xcc_Z,X86RM_Reg(e0Hi),tHi));
1732 addInstr(env, X86Instr_CMov32(Xcc_Z,X86RM_Reg(e0Lo),tLo));
1733 *rHi = tHi;
1734 *rLo = tLo;
1735 return;
1736 }
1737
sewardj597b71b2004-07-19 02:51:12 +00001738 /* 32 x 32 -> 64 multiply */
1739 if (e->tag == Iex_Binop
1740 && (e->Iex.Binop.op == Iop_MullU32
1741 || e->Iex.Binop.op == Iop_MullS32)) {
1742 /* get one operand into %eax, and the other into a R/M. Need to
1743 make an educated guess about which is better in which. */
sewardjd18d1bf2004-08-25 12:49:22 +00001744 HReg tLo = newVRegI(env);
1745 HReg tHi = newVRegI(env);
sewardj597b71b2004-07-19 02:51:12 +00001746 Bool syned = e->Iex.Binop.op == Iop_MullS32;
1747 X86RM* rmLeft = iselIntExpr_RM(env, e->Iex.Binop.arg1);
1748 HReg rRight = iselIntExpr_R(env, e->Iex.Binop.arg2);
sewardjd08f2d72004-12-01 23:19:36 +00001749 addInstr(env, mk_iMOVsd_RR(rRight, hregX86_EAX()));
sewardj597b71b2004-07-19 02:51:12 +00001750 addInstr(env, X86Instr_MulL(syned, Xss_32, rmLeft));
1751 /* Result is now in EDX:EAX. Tell the caller. */
sewardjd08f2d72004-12-01 23:19:36 +00001752 addInstr(env, mk_iMOVsd_RR(hregX86_EDX(), tHi));
1753 addInstr(env, mk_iMOVsd_RR(hregX86_EAX(), tLo));
sewardjd18d1bf2004-08-25 12:49:22 +00001754 *rHi = tHi;
1755 *rLo = tLo;
sewardj597b71b2004-07-19 02:51:12 +00001756 return;
1757 }
1758
sewardj5c34dc92004-07-19 12:48:11 +00001759 /* 64 x 32 -> (32(rem),32(div)) division */
1760 if (e->tag == Iex_Binop
1761 && (e->Iex.Binop.op == Iop_DivModU64to32
1762 || e->Iex.Binop.op == Iop_DivModS64to32)) {
1763 /* Get the 64-bit operand into edx:eax, and the other
1764 into any old R/M. */
1765 HReg sHi, sLo;
sewardjd18d1bf2004-08-25 12:49:22 +00001766 HReg tLo = newVRegI(env);
1767 HReg tHi = newVRegI(env);
sewardjacbfdd02004-07-30 14:08:17 +00001768 Bool syned = e->Iex.Binop.op == Iop_DivModS64to32;
sewardj5c34dc92004-07-19 12:48:11 +00001769 X86RM* rmRight = iselIntExpr_RM(env, e->Iex.Binop.arg2);
sewardjd08f2d72004-12-01 23:19:36 +00001770 iselInt64Expr(&sHi,&sLo, env, e->Iex.Binop.arg1);
1771 addInstr(env, mk_iMOVsd_RR(sHi, hregX86_EDX()));
1772 addInstr(env, mk_iMOVsd_RR(sLo, hregX86_EAX()));
sewardj5c34dc92004-07-19 12:48:11 +00001773 addInstr(env, X86Instr_Div(syned, Xss_32, rmRight));
sewardjd08f2d72004-12-01 23:19:36 +00001774 addInstr(env, mk_iMOVsd_RR(hregX86_EDX(), tHi));
1775 addInstr(env, mk_iMOVsd_RR(hregX86_EAX(), tLo));
sewardjd18d1bf2004-08-25 12:49:22 +00001776 *rHi = tHi;
1777 *rLo = tLo;
sewardj5c34dc92004-07-19 12:48:11 +00001778 return;
1779 }
1780
sewardje5854d62004-12-09 03:44:34 +00001781 /* Iop_Or64/And64/Xor64 */
sewardj218e29f2004-11-07 18:45:15 +00001782 if (e->tag == Iex_Binop
sewardjb4acca52004-11-21 13:45:05 +00001783 && (e->Iex.Binop.op == Iop_Or64
1784 || e->Iex.Binop.op == Iop_And64
1785 || e->Iex.Binop.op == Iop_Xor64)) {
sewardj218e29f2004-11-07 18:45:15 +00001786 HReg xLo, xHi, yLo, yHi;
1787 HReg tLo = newVRegI(env);
1788 HReg tHi = newVRegI(env);
sewardjb4acca52004-11-21 13:45:05 +00001789 X86AluOp op = e->Iex.Binop.op==Iop_Or64 ? Xalu_OR
1790 : e->Iex.Binop.op==Iop_And64 ? Xalu_AND
1791 : Xalu_XOR;
sewardjd08f2d72004-12-01 23:19:36 +00001792 iselInt64Expr(&xHi, &xLo, env, e->Iex.Binop.arg1);
1793 addInstr(env, mk_iMOVsd_RR(xHi, tHi));
1794 addInstr(env, mk_iMOVsd_RR(xLo, tLo));
1795 iselInt64Expr(&yHi, &yLo, env, e->Iex.Binop.arg2);
sewardjb4acca52004-11-21 13:45:05 +00001796 addInstr(env, X86Instr_Alu32R(op, X86RMI_Reg(yHi), tHi));
1797 addInstr(env, X86Instr_Alu32R(op, X86RMI_Reg(yLo), tLo));
sewardj218e29f2004-11-07 18:45:15 +00001798 *rHi = tHi;
1799 *rLo = tLo;
1800 return;
1801 }
1802
sewardj5c34dc92004-07-19 12:48:11 +00001803 /* 32HLto64(e1,e2) */
1804 if (e->tag == Iex_Binop
1805 && e->Iex.Binop.op == Iop_32HLto64) {
1806 *rHi = iselIntExpr_R(env, e->Iex.Binop.arg1);
1807 *rLo = iselIntExpr_R(env, e->Iex.Binop.arg2);
1808 return;
1809 }
1810
sewardjbb53f8c2004-08-14 11:50:01 +00001811 /* 32Sto64(e) */
1812 if (e->tag == Iex_Unop
1813 && e->Iex.Unop.op == Iop_32Sto64) {
1814 HReg tLo = newVRegI(env);
1815 HReg tHi = newVRegI(env);
1816 HReg src = iselIntExpr_R(env, e->Iex.Unop.arg);
sewardjd08f2d72004-12-01 23:19:36 +00001817 addInstr(env, mk_iMOVsd_RR(src,tHi));
1818 addInstr(env, mk_iMOVsd_RR(src,tLo));
sewardjbb53f8c2004-08-14 11:50:01 +00001819 addInstr(env, X86Instr_Sh32(Xsh_SAR, 31, X86RM_Reg(tHi)));
1820 *rHi = tHi;
1821 *rLo = tLo;
1822 return;
1823 }
1824
sewardjd08f2d72004-12-01 23:19:36 +00001825 /* 128{HI}to64 */
1826 if (e->tag == Iex_Unop
1827 && (e->Iex.Unop.op == Iop_128HIto64
1828 || e->Iex.Unop.op == Iop_128to64)) {
1829 Int off = e->Iex.Unop.op==Iop_128HIto64 ? 8 : 0;
1830 HReg tLo = newVRegI(env);
1831 HReg tHi = newVRegI(env);
1832 HReg vec = iselVecExpr(env, e->Iex.Unop.arg);
1833 X86AMode* esp0 = X86AMode_IR(0, hregX86_ESP());
1834 X86AMode* espLO = X86AMode_IR(off, hregX86_ESP());
1835 X86AMode* espHI = X86AMode_IR(off+4, hregX86_ESP());
sewardj855f32d2004-12-05 21:22:38 +00001836 sub_from_esp(env, 16);
sewardjd08f2d72004-12-01 23:19:36 +00001837 addInstr(env, X86Instr_SseLdSt(False/*store*/, vec, esp0));
1838 addInstr(env, X86Instr_Alu32R( Xalu_MOV, X86RMI_Mem(espLO), tLo ));
1839 addInstr(env, X86Instr_Alu32R( Xalu_MOV, X86RMI_Mem(espHI), tHi ));
sewardj855f32d2004-12-05 21:22:38 +00001840 add_to_esp(env, 16);
sewardjd08f2d72004-12-01 23:19:36 +00001841 *rHi = tHi;
1842 *rLo = tLo;
1843 return;
1844 }
1845
sewardjf27e1db2004-11-23 00:19:06 +00001846 /* 32Uto64(e) */
sewardjb4acca52004-11-21 13:45:05 +00001847 if (e->tag == Iex_Unop
sewardjf27e1db2004-11-23 00:19:06 +00001848 && e->Iex.Unop.op == Iop_32Uto64) {
sewardjb4acca52004-11-21 13:45:05 +00001849 HReg tLo = newVRegI(env);
1850 HReg tHi = newVRegI(env);
1851 HReg src = iselIntExpr_R(env, e->Iex.Unop.arg);
sewardjd08f2d72004-12-01 23:19:36 +00001852 addInstr(env, mk_iMOVsd_RR(src,tLo));
sewardjf27e1db2004-11-23 00:19:06 +00001853 addInstr(env, X86Instr_Alu32R(Xalu_MOV, X86RMI_Imm(0), tHi));
sewardjb4acca52004-11-21 13:45:05 +00001854 *rHi = tHi;
1855 *rLo = tLo;
1856 return;
1857 }
1858
sewardjb5874aa2004-11-04 16:57:50 +00001859 /* could do better than this, but for now ... */
1860 if (e->tag == Iex_Unop
1861 && e->Iex.Unop.op == Iop_1Sto64) {
1862 HReg tLo = newVRegI(env);
1863 HReg tHi = newVRegI(env);
1864 X86CondCode cond = iselCondCode(env, e->Iex.Unop.arg);
1865 addInstr(env, X86Instr_Set32(cond,tLo));
1866 addInstr(env, X86Instr_Sh32(Xsh_SHL, 31, X86RM_Reg(tLo)));
1867 addInstr(env, X86Instr_Sh32(Xsh_SAR, 31, X86RM_Reg(tLo)));
sewardjd08f2d72004-12-01 23:19:36 +00001868 addInstr(env, mk_iMOVsd_RR(tLo, tHi));
sewardjb5874aa2004-11-04 16:57:50 +00001869 *rHi = tHi;
1870 *rLo = tLo;
1871 return;
1872 }
1873
sewardjb4acca52004-11-21 13:45:05 +00001874 /* Not64(e) */
sewardje5427e82004-09-11 19:43:51 +00001875 if (e->tag == Iex_Unop
sewardjb4acca52004-11-21 13:45:05 +00001876 && e->Iex.Unop.op == Iop_Not64) {
sewardje5427e82004-09-11 19:43:51 +00001877 HReg tLo = newVRegI(env);
1878 HReg tHi = newVRegI(env);
sewardjb4acca52004-11-21 13:45:05 +00001879 HReg sHi, sLo;
sewardjd08f2d72004-12-01 23:19:36 +00001880 iselInt64Expr(&sHi, &sLo, env, e->Iex.Unop.arg);
1881 addInstr(env, mk_iMOVsd_RR(sHi, tHi));
1882 addInstr(env, mk_iMOVsd_RR(sLo, tLo));
sewardjb4acca52004-11-21 13:45:05 +00001883 addInstr(env, X86Instr_Unary32(Xun_NOT,X86RM_Reg(tHi)));
1884 addInstr(env, X86Instr_Unary32(Xun_NOT,X86RM_Reg(tLo)));
sewardje5427e82004-09-11 19:43:51 +00001885 *rHi = tHi;
1886 *rLo = tLo;
1887 return;
1888 }
1889
sewardj17442fe2004-09-20 14:54:28 +00001890 /* ReinterpF64asI64(e) */
1891 /* Given an IEEE754 double, produce an I64 with the same bit
1892 pattern. */
1893 if (e->tag == Iex_Unop
1894 && e->Iex.Unop.op == Iop_ReinterpF64asI64) {
1895 HReg rf = iselDblExpr(env, e->Iex.Unop.arg);
1896 HReg tLo = newVRegI(env);
1897 HReg tHi = newVRegI(env);
1898 X86AMode* zero_esp = X86AMode_IR(0, hregX86_ESP());
1899 X86AMode* four_esp = X86AMode_IR(4, hregX86_ESP());
sewardj3bca9062004-12-04 14:36:09 +00001900 /* paranoia */
1901 set_FPU_rounding_default(env);
sewardj17442fe2004-09-20 14:54:28 +00001902 /* subl $8, %esp */
sewardj855f32d2004-12-05 21:22:38 +00001903 sub_from_esp(env, 8);
sewardj17442fe2004-09-20 14:54:28 +00001904 /* gstD %rf, 0(%esp) */
1905 addInstr(env,
1906 X86Instr_FpLdSt(False/*store*/, 8, rf, zero_esp));
1907 /* movl 0(%esp), %tLo */
1908 addInstr(env,
1909 X86Instr_Alu32R(Xalu_MOV, X86RMI_Mem(zero_esp), tLo));
1910 /* movl 4(%esp), %tHi */
1911 addInstr(env,
1912 X86Instr_Alu32R(Xalu_MOV, X86RMI_Mem(four_esp), tHi));
1913 /* addl $8, %esp */
sewardj855f32d2004-12-05 21:22:38 +00001914 add_to_esp(env, 8);
sewardj17442fe2004-09-20 14:54:28 +00001915 *rHi = tHi;
1916 *rLo = tLo;
1917 return;
1918 }
1919
sewardj5c34dc92004-07-19 12:48:11 +00001920 /* 64-bit shifts */
1921 if (e->tag == Iex_Binop
1922 && e->Iex.Binop.op == Iop_Shl64) {
1923 /* We use the same ingenious scheme as gcc. Put the value
1924 to be shifted into %hi:%lo, and the shift amount into %cl.
1925 Then (dsts on right, a la ATT syntax):
1926
1927 shldl %cl, %lo, %hi -- make %hi be right for the shift amt
1928 -- %cl % 32
1929 shll %cl, %lo -- make %lo be right for the shift amt
1930 -- %cl % 32
1931
1932 Now, if (shift amount % 64) is in the range 32 .. 63, we have
1933 to do a fixup, which puts the result low half into the result
1934 high half, and zeroes the low half:
1935
1936 testl $32, %ecx
1937
1938 cmovnz %lo, %hi
1939 movl $0, %tmp -- sigh; need yet another reg
1940 cmovnz %tmp, %lo
1941 */
1942 HReg rAmt, sHi, sLo, tHi, tLo, tTemp;
1943 tLo = newVRegI(env);
1944 tHi = newVRegI(env);
1945 tTemp = newVRegI(env);
1946 rAmt = iselIntExpr_R(env, e->Iex.Binop.arg2);
sewardjd08f2d72004-12-01 23:19:36 +00001947 iselInt64Expr(&sHi,&sLo, env, e->Iex.Binop.arg1);
1948 addInstr(env, mk_iMOVsd_RR(rAmt, hregX86_ECX()));
1949 addInstr(env, mk_iMOVsd_RR(sHi, tHi));
1950 addInstr(env, mk_iMOVsd_RR(sLo, tLo));
sewardj5c34dc92004-07-19 12:48:11 +00001951 /* Ok. Now shift amt is in %ecx, and value is in tHi/tLo and
1952 those regs are legitimately modifiable. */
sewardje5f384c2004-07-30 16:17:28 +00001953 addInstr(env, X86Instr_Sh3232(Xsh_SHL, 0/*%cl*/, tLo, tHi));
sewardj5c34dc92004-07-19 12:48:11 +00001954 addInstr(env, X86Instr_Sh32(Xsh_SHL, 0/*%cl*/, X86RM_Reg(tLo)));
sewardje8c922f2004-07-23 01:34:11 +00001955 addInstr(env, X86Instr_Test32(X86RI_Imm(32), X86RM_Reg(hregX86_ECX())));
sewardj5c34dc92004-07-19 12:48:11 +00001956 addInstr(env, X86Instr_CMov32(Xcc_NZ, X86RM_Reg(tLo), tHi));
1957 addInstr(env, X86Instr_Alu32R(Xalu_MOV, X86RMI_Imm(0), tTemp));
1958 addInstr(env, X86Instr_CMov32(Xcc_NZ, X86RM_Reg(tTemp), tLo));
1959 *rHi = tHi;
1960 *rLo = tLo;
1961 return;
1962 }
1963
sewardj68511542004-07-28 00:15:44 +00001964 if (e->tag == Iex_Binop
1965 && e->Iex.Binop.op == Iop_Shr64) {
1966 /* We use the same ingenious scheme as gcc. Put the value
1967 to be shifted into %hi:%lo, and the shift amount into %cl.
1968 Then:
1969
1970 shrdl %cl, %hi, %lo -- make %lo be right for the shift amt
1971 -- %cl % 32
sewardj80f8c302004-07-29 22:21:31 +00001972 shrl %cl, %hi -- make %hi be right for the shift amt
sewardj68511542004-07-28 00:15:44 +00001973 -- %cl % 32
1974
1975 Now, if (shift amount % 64) is in the range 32 .. 63, we have
1976 to do a fixup, which puts the result high half into the result
1977 low half, and zeroes the high half:
1978
1979 testl $32, %ecx
1980
1981 cmovnz %hi, %lo
1982 movl $0, %tmp -- sigh; need yet another reg
1983 cmovnz %tmp, %hi
1984 */
1985 HReg rAmt, sHi, sLo, tHi, tLo, tTemp;
1986 tLo = newVRegI(env);
1987 tHi = newVRegI(env);
1988 tTemp = newVRegI(env);
1989 rAmt = iselIntExpr_R(env, e->Iex.Binop.arg2);
sewardjd08f2d72004-12-01 23:19:36 +00001990 iselInt64Expr(&sHi,&sLo, env, e->Iex.Binop.arg1);
1991 addInstr(env, mk_iMOVsd_RR(rAmt, hregX86_ECX()));
1992 addInstr(env, mk_iMOVsd_RR(sHi, tHi));
1993 addInstr(env, mk_iMOVsd_RR(sLo, tLo));
sewardj68511542004-07-28 00:15:44 +00001994 /* Ok. Now shift amt is in %ecx, and value is in tHi/tLo and
1995 those regs are legitimately modifiable. */
sewardje5f384c2004-07-30 16:17:28 +00001996 addInstr(env, X86Instr_Sh3232(Xsh_SHR, 0/*%cl*/, tHi, tLo));
sewardj68511542004-07-28 00:15:44 +00001997 addInstr(env, X86Instr_Sh32(Xsh_SHR, 0/*%cl*/, X86RM_Reg(tHi)));
1998 addInstr(env, X86Instr_Test32(X86RI_Imm(32), X86RM_Reg(hregX86_ECX())));
1999 addInstr(env, X86Instr_CMov32(Xcc_NZ, X86RM_Reg(tHi), tLo));
2000 addInstr(env, X86Instr_Alu32R(Xalu_MOV, X86RMI_Imm(0), tTemp));
2001 addInstr(env, X86Instr_CMov32(Xcc_NZ, X86RM_Reg(tTemp), tHi));
2002 *rHi = tHi;
2003 *rLo = tLo;
2004 return;
2005 }
2006
sewardjcfded9a2004-09-09 11:44:16 +00002007 /* F64 -> I64 */
2008 /* Sigh, this is an almost exact copy of the F64 -> I32/I16 case.
2009 Unfortunately I see no easy way to avoid the duplication. */
2010 if (e->tag == Iex_Binop
2011 && e->Iex.Binop.op == Iop_F64toI64) {
sewardj4cb918d2004-12-03 19:43:31 +00002012 HReg rf = iselDblExpr(env, e->Iex.Binop.arg2);
2013 HReg tLo = newVRegI(env);
2014 HReg tHi = newVRegI(env);
sewardjcfded9a2004-09-09 11:44:16 +00002015
2016 /* Used several times ... */
2017 /* Careful ... this sharing is only safe because
2018 zero_esp/four_esp do not hold any registers which the
2019 register allocator could attempt to swizzle later. */
2020 X86AMode* zero_esp = X86AMode_IR(0, hregX86_ESP());
2021 X86AMode* four_esp = X86AMode_IR(4, hregX86_ESP());
2022
2023 /* rf now holds the value to be converted, and rrm holds the
2024 rounding mode value, encoded as per the IRRoundingMode enum.
2025 The first thing to do is set the FPU's rounding mode
2026 accordingly. */
2027
sewardj4cb918d2004-12-03 19:43:31 +00002028 /* Create a space for the format conversion. */
sewardjcfded9a2004-09-09 11:44:16 +00002029 /* subl $8, %esp */
sewardj855f32d2004-12-05 21:22:38 +00002030 sub_from_esp(env, 8);
sewardj4cb918d2004-12-03 19:43:31 +00002031
2032 /* Set host rounding mode */
2033 set_FPU_rounding_mode( env, e->Iex.Binop.arg1 );
sewardjcfded9a2004-09-09 11:44:16 +00002034
2035 /* gistll %rf, 0(%esp) */
2036 addInstr(env, X86Instr_FpLdStI(False/*store*/, 8, rf, zero_esp));
2037
2038 /* movl 0(%esp), %dstLo */
2039 /* movl 4(%esp), %dstHi */
2040 addInstr(env, X86Instr_Alu32R(
2041 Xalu_MOV, X86RMI_Mem(zero_esp), tLo));
2042 addInstr(env, X86Instr_Alu32R(
2043 Xalu_MOV, X86RMI_Mem(four_esp), tHi));
2044
sewardj4cb918d2004-12-03 19:43:31 +00002045 /* Restore default FPU rounding. */
2046 set_FPU_rounding_default( env );
sewardjcfded9a2004-09-09 11:44:16 +00002047
2048 /* addl $8, %esp */
sewardj855f32d2004-12-05 21:22:38 +00002049 add_to_esp(env, 8);
sewardjcfded9a2004-09-09 11:44:16 +00002050
2051 *rHi = tHi;
2052 *rLo = tLo;
sewardjc4be80c2004-09-10 16:17:45 +00002053 return;
2054 }
2055
sewardj33fa73e2004-10-24 19:19:37 +00002056 /* --------- CCALL --------- */
2057 if (e->tag == Iex_CCall) {
sewardj77352542004-10-30 20:39:01 +00002058 HReg tLo = newVRegI(env);
2059 HReg tHi = newVRegI(env);
sewardj33fa73e2004-10-24 19:19:37 +00002060
sewardj77352542004-10-30 20:39:01 +00002061 /* Marshal args, do the call, clear stack. */
sewardj4b861de2004-11-03 15:24:42 +00002062 doHelperCall( env, False, NULL, e->Iex.CCall.cee, e->Iex.CCall.args );
sewardj33fa73e2004-10-24 19:19:37 +00002063
sewardjd08f2d72004-12-01 23:19:36 +00002064 addInstr(env, mk_iMOVsd_RR(hregX86_EDX(), tHi));
2065 addInstr(env, mk_iMOVsd_RR(hregX86_EAX(), tLo));
sewardj33fa73e2004-10-24 19:19:37 +00002066 *rHi = tHi;
2067 *rLo = tLo;
2068 return;
2069 }
2070
sewardj597b71b2004-07-19 02:51:12 +00002071 ppIRExpr(e);
sewardjd08f2d72004-12-01 23:19:36 +00002072 vpanic("iselInt64Expr");
sewardj597b71b2004-07-19 02:51:12 +00002073}
2074
2075
sewardjd08f2d72004-12-01 23:19:36 +00002076/*---------------------------------------------------------*/
2077/*--- ISEL: Floating point expressions (32 bit) ---*/
2078/*---------------------------------------------------------*/
2079
2080/* Nothing interesting here; really just wrappers for
2081 64-bit stuff. */
2082
2083static HReg iselFltExpr ( ISelEnv* env, IRExpr* e )
2084{
2085 HReg r = iselFltExpr_wrk( env, e );
2086# if 0
2087 vex_printf("\n"); ppIRExpr(e); vex_printf("\n");
2088# endif
2089 vassert(hregClass(r) == HRcFlt64); /* yes, really Flt64 */
2090 vassert(hregIsVirtual(r));
2091 return r;
2092}
2093
2094/* DO NOT CALL THIS DIRECTLY */
2095static HReg iselFltExpr_wrk ( ISelEnv* env, IRExpr* e )
2096{
2097 IRType ty = typeOfIRExpr(env->type_env,e);
2098 vassert(ty == Ity_F32);
2099
2100 if (e->tag == Iex_Tmp) {
2101 return lookupIRTemp(env, e->Iex.Tmp.tmp);
2102 }
2103
2104 if (e->tag == Iex_LDle) {
2105 X86AMode* am;
2106 HReg res = newVRegF(env);
2107 vassert(e->Iex.LDle.ty == Ity_F32);
2108 am = iselIntExpr_AMode(env, e->Iex.LDle.addr);
2109 addInstr(env, X86Instr_FpLdSt(True/*load*/, 4, res, am));
2110 return res;
2111 }
2112
sewardj3bca9062004-12-04 14:36:09 +00002113 if (e->tag == Iex_Binop
2114 && e->Iex.Binop.op == Iop_F64toF32) {
2115 /* Although the result is still held in a standard FPU register,
2116 we need to round it to reflect the loss of accuracy/range
2117 entailed in casting it to a 32-bit float. */
2118 HReg dst = newVRegF(env);
2119 HReg src = iselDblExpr(env, e->Iex.Binop.arg2);
2120 set_FPU_rounding_mode( env, e->Iex.Binop.arg1 );
2121 addInstr(env, X86Instr_Fp64to32(src,dst));
2122 set_FPU_rounding_default( env );
2123 return dst;
sewardjd08f2d72004-12-01 23:19:36 +00002124 }
2125
sewardj67e002d2004-12-02 18:16:33 +00002126 if (e->tag == Iex_Get) {
2127 X86AMode* am = X86AMode_IR( e->Iex.Get.offset,
2128 hregX86_EBP() );
2129 HReg res = newVRegF(env);
2130 addInstr(env, X86Instr_FpLdSt( True/*load*/, 4, res, am ));
2131 return res;
2132 }
2133
sewardjfd226452004-12-07 19:02:18 +00002134 if (e->tag == Iex_Unop
2135 && e->Iex.Unop.op == Iop_ReinterpI32asF32) {
2136 /* Given an I32, produce an IEEE754 float with the same bit
2137 pattern. */
2138 HReg dst = newVRegF(env);
2139 X86RMI* rmi = iselIntExpr_RMI(env, e->Iex.Unop.arg);
2140 /* paranoia */
2141 addInstr(env, X86Instr_Push(rmi));
2142 addInstr(env, X86Instr_FpLdSt(
2143 True/*load*/, 4, dst,
2144 X86AMode_IR(0, hregX86_ESP())));
2145 add_to_esp(env, 4);
2146 return dst;
2147 }
2148
sewardjd08f2d72004-12-01 23:19:36 +00002149 ppIRExpr(e);
2150 vpanic("iselFltExpr_wrk");
2151}
2152
sewardj4042c7e2004-07-18 01:28:30 +00002153
sewardjc97096c2004-06-30 09:28:04 +00002154/*---------------------------------------------------------*/
sewardj3196daf2004-08-13 00:18:58 +00002155/*--- ISEL: Floating point expressions (64 bit) ---*/
2156/*---------------------------------------------------------*/
2157
2158/* Compute a 64-bit floating point value into a register, the identity
2159 of which is returned. As with iselIntExpr_R, the reg may be either
2160 real or virtual; in any case it must not be changed by subsequent
2161 code emitted by the caller. */
2162
sewardj3fc76d22004-08-31 11:47:54 +00002163/* IEEE 754 formats. From http://www.freesoft.org/CIE/RFC/1832/32.htm:
2164
2165 Type S (1 bit) E (11 bits) F (52 bits)
2166 ---- --------- ----------- -----------
2167 signalling NaN u 2047 (max) .0uuuuu---u
2168 (with at least
2169 one 1 bit)
2170 quiet NaN u 2047 (max) .1uuuuu---u
2171
2172 negative infinity 1 2047 (max) .000000---0
2173
2174 positive infinity 0 2047 (max) .000000---0
2175
2176 negative zero 1 0 .000000---0
2177
2178 positive zero 0 0 .000000---0
2179*/
2180
sewardj3196daf2004-08-13 00:18:58 +00002181static HReg iselDblExpr ( ISelEnv* env, IRExpr* e )
2182{
sewardjd08f2d72004-12-01 23:19:36 +00002183 HReg r = iselDblExpr_wrk( env, e );
2184# if 0
2185 vex_printf("\n"); ppIRExpr(e); vex_printf("\n");
2186# endif
2187 vassert(hregClass(r) == HRcFlt64);
2188 vassert(hregIsVirtual(r));
2189 return r;
2190}
2191
2192/* DO NOT CALL THIS DIRECTLY */
2193static HReg iselDblExpr_wrk ( ISelEnv* env, IRExpr* e )
2194{
sewardj33124f62004-08-30 17:54:18 +00002195 IRType ty = typeOfIRExpr(env->type_env,e);
sewardj3196daf2004-08-13 00:18:58 +00002196 vassert(e);
sewardj33124f62004-08-30 17:54:18 +00002197 vassert(ty == Ity_F64);
sewardj3196daf2004-08-13 00:18:58 +00002198
sewardjbb53f8c2004-08-14 11:50:01 +00002199 if (e->tag == Iex_Tmp) {
2200 return lookupIRTemp(env, e->Iex.Tmp.tmp);
2201 }
2202
sewardja58ea662004-08-15 03:12:41 +00002203 if (e->tag == Iex_Const) {
sewardj17442fe2004-09-20 14:54:28 +00002204 union { UInt u32x2[2]; ULong u64; Double f64; } u;
sewardja58ea662004-08-15 03:12:41 +00002205 HReg freg = newVRegF(env);
2206 vassert(sizeof(u) == 8);
sewardj17442fe2004-09-20 14:54:28 +00002207 vassert(sizeof(u.u64) == 8);
sewardja58ea662004-08-15 03:12:41 +00002208 vassert(sizeof(u.f64) == 8);
sewardj17442fe2004-09-20 14:54:28 +00002209 vassert(sizeof(u.u32x2) == 8);
sewardj3fc76d22004-08-31 11:47:54 +00002210
2211 if (e->Iex.Const.con->tag == Ico_F64) {
2212 u.f64 = e->Iex.Const.con->Ico.F64;
sewardj17442fe2004-09-20 14:54:28 +00002213 }
2214 else if (e->Iex.Const.con->tag == Ico_F64i) {
2215 u.u64 = e->Iex.Const.con->Ico.F64i;
sewardj3fc76d22004-08-31 11:47:54 +00002216 }
2217 else
2218 vpanic("iselDblExpr(x86): const");
2219
sewardj17442fe2004-09-20 14:54:28 +00002220 addInstr(env, X86Instr_Push(X86RMI_Imm(u.u32x2[1])));
2221 addInstr(env, X86Instr_Push(X86RMI_Imm(u.u32x2[0])));
sewardja58ea662004-08-15 03:12:41 +00002222 addInstr(env, X86Instr_FpLdSt(True/*load*/, 8, freg,
2223 X86AMode_IR(0, hregX86_ESP())));
sewardj855f32d2004-12-05 21:22:38 +00002224 add_to_esp(env, 8);
sewardja58ea662004-08-15 03:12:41 +00002225 return freg;
2226 }
2227
sewardj3196daf2004-08-13 00:18:58 +00002228 if (e->tag == Iex_LDle) {
2229 X86AMode* am;
2230 HReg res = newVRegF(env);
2231 vassert(e->Iex.LDle.ty == Ity_F64);
2232 am = iselIntExpr_AMode(env, e->Iex.LDle.addr);
2233 addInstr(env, X86Instr_FpLdSt(True/*load*/, 8, res, am));
2234 return res;
2235 }
2236
sewardjfd226452004-12-07 19:02:18 +00002237 if (e->tag == Iex_Get) {
2238 X86AMode* am = X86AMode_IR( e->Iex.Get.offset,
2239 hregX86_EBP() );
2240 HReg res = newVRegF(env);
2241 addInstr(env, X86Instr_FpLdSt( True/*load*/, 8, res, am ));
2242 return res;
2243 }
2244
sewardjbb53f8c2004-08-14 11:50:01 +00002245 if (e->tag == Iex_GetI) {
sewardj2d3f77c2004-09-22 23:49:09 +00002246 X86AMode* am
2247 = genGuestArrayOffset(
2248 env, e->Iex.GetI.descr,
sewardjeeac8412004-11-02 00:26:55 +00002249 e->Iex.GetI.ix, e->Iex.GetI.bias );
sewardjbb53f8c2004-08-14 11:50:01 +00002250 HReg res = newVRegF(env);
sewardj2d3f77c2004-09-22 23:49:09 +00002251 addInstr(env, X86Instr_FpLdSt( True/*load*/, 8, res, am ));
sewardjbb53f8c2004-08-14 11:50:01 +00002252 return res;
2253 }
2254
2255 if (e->tag == Iex_Binop) {
2256 X86FpOp fpop = Xfp_INVALID;
2257 switch (e->Iex.Binop.op) {
sewardj06c32a02004-09-12 12:07:34 +00002258 case Iop_AddF64: fpop = Xfp_ADD; break;
2259 case Iop_SubF64: fpop = Xfp_SUB; break;
2260 case Iop_MulF64: fpop = Xfp_MUL; break;
2261 case Iop_DivF64: fpop = Xfp_DIV; break;
2262 case Iop_ScaleF64: fpop = Xfp_SCALE; break;
2263 case Iop_AtanF64: fpop = Xfp_ATAN; break;
2264 case Iop_Yl2xF64: fpop = Xfp_YL2X; break;
2265 case Iop_Yl2xp1F64: fpop = Xfp_YL2XP1; break;
2266 case Iop_PRemF64: fpop = Xfp_PREM; break;
sewardj442d0be2004-10-15 22:57:13 +00002267 case Iop_PRem1F64: fpop = Xfp_PREM1; break;
sewardjbb53f8c2004-08-14 11:50:01 +00002268 default: break;
2269 }
2270 if (fpop != Xfp_INVALID) {
2271 HReg res = newVRegF(env);
2272 HReg srcL = iselDblExpr(env, e->Iex.Binop.arg1);
2273 HReg srcR = iselDblExpr(env, e->Iex.Binop.arg2);
2274 addInstr(env, X86Instr_FpBinary(fpop,srcL,srcR,res));
2275 return res;
2276 }
2277 }
2278
sewardje6709112004-09-10 18:37:18 +00002279 if (e->tag == Iex_Binop && e->Iex.Binop.op == Iop_RoundF64) {
sewardj4cb918d2004-12-03 19:43:31 +00002280 HReg rf = iselDblExpr(env, e->Iex.Binop.arg2);
2281 HReg dst = newVRegF(env);
sewardje6709112004-09-10 18:37:18 +00002282
sewardj4cb918d2004-12-03 19:43:31 +00002283 /* rf now holds the value to be rounded. The first thing to do
2284 is set the FPU's rounding mode accordingly. */
sewardje6709112004-09-10 18:37:18 +00002285
sewardj4cb918d2004-12-03 19:43:31 +00002286 /* Set host rounding mode */
2287 set_FPU_rounding_mode( env, e->Iex.Binop.arg1 );
sewardje6709112004-09-10 18:37:18 +00002288
2289 /* grndint %rf, %dst */
2290 addInstr(env, X86Instr_FpUnary(Xfp_ROUND, rf, dst));
2291
sewardj4cb918d2004-12-03 19:43:31 +00002292 /* Restore default FPU rounding. */
2293 set_FPU_rounding_default( env );
sewardje6709112004-09-10 18:37:18 +00002294
sewardj4cb918d2004-12-03 19:43:31 +00002295 return dst;
2296 }
2297
2298 if (e->tag == Iex_Binop && e->Iex.Binop.op == Iop_I64toF64) {
2299 HReg dst = newVRegF(env);
2300 HReg rHi,rLo;
2301 iselInt64Expr( &rHi, &rLo, env, e->Iex.Binop.arg2);
2302 addInstr(env, X86Instr_Push(X86RMI_Reg(rHi)));
2303 addInstr(env, X86Instr_Push(X86RMI_Reg(rLo)));
2304
2305 /* Set host rounding mode */
2306 set_FPU_rounding_mode( env, e->Iex.Binop.arg1 );
2307
2308 addInstr(env, X86Instr_FpLdStI(
2309 True/*load*/, 8, dst,
2310 X86AMode_IR(0, hregX86_ESP())));
2311
2312 /* Restore default FPU rounding. */
2313 set_FPU_rounding_default( env );
2314
sewardj855f32d2004-12-05 21:22:38 +00002315 add_to_esp(env, 8);
sewardje6709112004-09-10 18:37:18 +00002316 return dst;
2317 }
2318
sewardjbb53f8c2004-08-14 11:50:01 +00002319 if (e->tag == Iex_Unop) {
sewardjcfded9a2004-09-09 11:44:16 +00002320 X86FpOp fpop = Xfp_INVALID;
2321 switch (e->Iex.Unop.op) {
sewardj883b00b2004-09-11 09:30:24 +00002322 case Iop_NegF64: fpop = Xfp_NEG; break;
2323 case Iop_AbsF64: fpop = Xfp_ABS; break;
sewardjc4be80c2004-09-10 16:17:45 +00002324 case Iop_SqrtF64: fpop = Xfp_SQRT; break;
2325 case Iop_SinF64: fpop = Xfp_SIN; break;
2326 case Iop_CosF64: fpop = Xfp_COS; break;
sewardj99016a72004-10-15 22:09:17 +00002327 case Iop_TanF64: fpop = Xfp_TAN; break;
sewardj06c32a02004-09-12 12:07:34 +00002328 case Iop_2xm1F64: fpop = Xfp_2XM1; break;
sewardjcfded9a2004-09-09 11:44:16 +00002329 default: break;
2330 }
2331 if (fpop != Xfp_INVALID) {
2332 HReg res = newVRegF(env);
2333 HReg src = iselDblExpr(env, e->Iex.Unop.arg);
2334 addInstr(env, X86Instr_FpUnary(fpop,src,res));
2335 return res;
2336 }
2337 }
2338
2339 if (e->tag == Iex_Unop) {
sewardj89cd0932004-09-08 18:23:25 +00002340 switch (e->Iex.Unop.op) {
2341 case Iop_I32toF64: {
2342 HReg dst = newVRegF(env);
2343 HReg ri = iselIntExpr_R(env, e->Iex.Unop.arg);
2344 addInstr(env, X86Instr_Push(X86RMI_Reg(ri)));
sewardj4cb918d2004-12-03 19:43:31 +00002345 set_FPU_rounding_default(env);
sewardj89cd0932004-09-08 18:23:25 +00002346 addInstr(env, X86Instr_FpLdStI(
2347 True/*load*/, 4, dst,
2348 X86AMode_IR(0, hregX86_ESP())));
sewardj855f32d2004-12-05 21:22:38 +00002349 add_to_esp(env, 4);
sewardj89cd0932004-09-08 18:23:25 +00002350 return dst;
2351 }
sewardj17442fe2004-09-20 14:54:28 +00002352 case Iop_ReinterpI64asF64: {
2353 /* Given an I64, produce an IEEE754 double with the same
2354 bit pattern. */
2355 HReg dst = newVRegF(env);
2356 HReg rHi, rLo;
sewardjd08f2d72004-12-01 23:19:36 +00002357 iselInt64Expr( &rHi, &rLo, env, e->Iex.Unop.arg);
sewardj3bca9062004-12-04 14:36:09 +00002358 /* paranoia */
2359 set_FPU_rounding_default(env);
sewardj17442fe2004-09-20 14:54:28 +00002360 addInstr(env, X86Instr_Push(X86RMI_Reg(rHi)));
2361 addInstr(env, X86Instr_Push(X86RMI_Reg(rLo)));
2362 addInstr(env, X86Instr_FpLdSt(
2363 True/*load*/, 8, dst,
2364 X86AMode_IR(0, hregX86_ESP())));
sewardj855f32d2004-12-05 21:22:38 +00002365 add_to_esp(env, 8);
sewardj17442fe2004-09-20 14:54:28 +00002366 return dst;
2367 }
sewardj89cd0932004-09-08 18:23:25 +00002368 case Iop_F32toF64:
2369 /* this is a no-op */
2370 return iselFltExpr(env, e->Iex.Unop.arg);
2371 default:
2372 break;
sewardjbb53f8c2004-08-14 11:50:01 +00002373 }
2374 }
2375
sewardj33124f62004-08-30 17:54:18 +00002376 /* --------- MULTIPLEX --------- */
2377 if (e->tag == Iex_Mux0X) {
2378 if (ty == Ity_F64
2379 && typeOfIRExpr(env->type_env,e->Iex.Mux0X.cond) == Ity_I8) {
2380 HReg r8 = iselIntExpr_R(env, e->Iex.Mux0X.cond);
2381 HReg rX = iselDblExpr(env, e->Iex.Mux0X.exprX);
2382 HReg r0 = iselDblExpr(env, e->Iex.Mux0X.expr0);
2383 HReg dst = newVRegF(env);
sewardj3fc76d22004-08-31 11:47:54 +00002384 addInstr(env, X86Instr_FpUnary(Xfp_MOV,rX,dst));
sewardj33124f62004-08-30 17:54:18 +00002385 addInstr(env, X86Instr_Test32(X86RI_Imm(0xFF), X86RM_Reg(r8)));
2386 addInstr(env, X86Instr_FpCMov(Xcc_Z,r0,dst));
2387 return dst;
2388 }
2389 }
2390
sewardj3196daf2004-08-13 00:18:58 +00002391 ppIRExpr(e);
sewardjd08f2d72004-12-01 23:19:36 +00002392 vpanic("iselDblExpr_wrk");
sewardj3196daf2004-08-13 00:18:58 +00002393}
2394
2395
sewardjd08f2d72004-12-01 23:19:36 +00002396/*---------------------------------------------------------*/
2397/*--- ISEL: SIMD (Vector) expressions, 128 bit. ---*/
2398/*---------------------------------------------------------*/
2399
2400static HReg iselVecExpr ( ISelEnv* env, IRExpr* e )
2401{
2402 HReg r = iselVecExpr_wrk( env, e );
2403# if 0
2404 vex_printf("\n"); ppIRExpr(e); vex_printf("\n");
2405# endif
2406 vassert(hregClass(r) == HRcVec128);
2407 vassert(hregIsVirtual(r));
2408 return r;
2409}
2410
2411
2412/* DO NOT CALL THIS DIRECTLY */
2413static HReg iselVecExpr_wrk ( ISelEnv* env, IRExpr* e )
2414{
sewardj164f9272004-12-09 00:39:32 +00002415 Bool arg1isEReg = False;
sewardj1e6ad742004-12-02 16:16:11 +00002416 X86SseOp op = Xsse_INVALID;
2417 IRType ty = typeOfIRExpr(env->type_env,e);
sewardjd08f2d72004-12-01 23:19:36 +00002418 vassert(e);
2419 vassert(ty == Ity_V128);
2420
2421 if (e->tag == Iex_Tmp) {
2422 return lookupIRTemp(env, e->Iex.Tmp.tmp);
2423 }
2424
2425 if (e->tag == Iex_Get) {
2426 HReg dst = newVRegV(env);
2427 addInstr(env, X86Instr_SseLdSt(
2428 True/*load*/,
2429 dst,
2430 X86AMode_IR(e->Iex.Get.offset, hregX86_EBP())
2431 )
2432 );
2433 return dst;
2434 }
2435
sewardj1e6ad742004-12-02 16:16:11 +00002436 if (e->tag == Iex_LDle) {
2437 HReg dst = newVRegV(env);
2438 X86AMode* am = iselIntExpr_AMode(env, e->Iex.LDle.addr);
2439 addInstr(env, X86Instr_SseLdSt( True/*load*/, dst, am ));
2440 return dst;
2441 }
2442
2443 if (e->tag == Iex_Const) {
2444 HReg dst = newVRegV(env);
2445 vassert(e->Iex.Const.con->tag == Ico_V128);
2446 addInstr(env, X86Instr_SseConst(e->Iex.Const.con->Ico.V128, dst));
2447 return dst;
2448 }
2449
sewardj0bd7ce62004-12-05 02:47:40 +00002450 if (e->tag == Iex_Unop) {
2451 switch (e->Iex.Unop.op) {
2452
sewardj70f676d2004-12-10 14:59:57 +00002453 case Iop_CmpNEZ32x4: {
2454 /* sigh, we have to generate crappy code for SSE1 */
2455 /* basically, the idea is: for each lane:
2456 movl lane, %r ; negl %r (now CF = lane==0 ? 0 : 1)
2457 sbbl %r, %r (now %r = 1Sto32(CF))
2458 movl %r, lane
2459 */
2460 Int i;
2461 X86AMode* am;
2462 X86AMode* esp0 = X86AMode_IR(0, hregX86_ESP());
2463 HReg arg = iselVecExpr(env, e->Iex.Unop.arg);
2464 HReg dst = newVRegV(env);
2465 HReg r32 = newVRegI(env);
2466 sub_from_esp(env, 16);
2467 addInstr(env, X86Instr_SseLdSt(False/*store*/, arg, esp0));
2468 for (i = 0; i < 4; i++) {
2469 am = X86AMode_IR(i*4, hregX86_ESP());
2470 addInstr(env, X86Instr_Alu32R(Xalu_MOV, X86RMI_Mem(am), r32));
2471 addInstr(env, X86Instr_Unary32(Xun_NEG, X86RM_Reg(r32)));
2472 addInstr(env, X86Instr_Alu32R(Xalu_SBB, X86RMI_Reg(r32), r32));
2473 addInstr(env, X86Instr_Alu32M(Xalu_MOV, X86RI_Reg(r32), am));
2474 }
2475 addInstr(env, X86Instr_SseLdSt(True/*load*/, dst, esp0));
2476 add_to_esp(env, 16);
2477 return dst;
2478 }
2479
sewardjc1e7dfc2004-12-05 19:29:45 +00002480 case Iop_Recip32Fx4: op = Xsse_RCPF; goto do_32Fx4_unary;
2481 case Iop_RSqrt32Fx4: op = Xsse_RSQRTF; goto do_32Fx4_unary;
2482 case Iop_Sqrt32Fx4: op = Xsse_SQRTF; goto do_32Fx4_unary;
sewardj0bd7ce62004-12-05 02:47:40 +00002483 do_32Fx4_unary:
2484 {
2485 HReg arg = iselVecExpr(env, e->Iex.Unop.arg);
2486 HReg dst = newVRegV(env);
2487 addInstr(env, X86Instr_Sse32Fx4(op, arg, dst));
2488 return dst;
2489 }
2490
sewardj636ad762004-12-07 11:16:04 +00002491 case Iop_Recip64Fx2: op = Xsse_RCPF; goto do_64Fx2_unary;
2492 case Iop_RSqrt64Fx2: op = Xsse_RSQRTF; goto do_64Fx2_unary;
2493 case Iop_Sqrt64Fx2: op = Xsse_SQRTF; goto do_64Fx2_unary;
2494 do_64Fx2_unary:
2495 {
2496 HReg arg = iselVecExpr(env, e->Iex.Unop.arg);
2497 HReg dst = newVRegV(env);
2498 addInstr(env, X86Instr_Sse64Fx2(op, arg, dst));
2499 return dst;
2500 }
2501
sewardjc1e7dfc2004-12-05 19:29:45 +00002502 case Iop_Recip32F0x4: op = Xsse_RCPF; goto do_32F0x4_unary;
2503 case Iop_RSqrt32F0x4: op = Xsse_RSQRTF; goto do_32F0x4_unary;
2504 case Iop_Sqrt32F0x4: op = Xsse_SQRTF; goto do_32F0x4_unary;
sewardj0bd7ce62004-12-05 02:47:40 +00002505 do_32F0x4_unary:
2506 {
sewardj129b3d92004-12-05 15:42:05 +00002507 /* A bit subtle. We have to copy the arg to the result
2508 register first, because actually doing the SSE scalar insn
2509 leaves the upper 3/4 of the destination register
2510 unchanged. Whereas the required semantics of these
2511 primops is that the upper 3/4 is simply copied in from the
2512 argument. */
sewardj0bd7ce62004-12-05 02:47:40 +00002513 HReg arg = iselVecExpr(env, e->Iex.Unop.arg);
2514 HReg dst = newVRegV(env);
sewardj129b3d92004-12-05 15:42:05 +00002515 addInstr(env, mk_vMOVsd_RR(arg, dst));
sewardj0bd7ce62004-12-05 02:47:40 +00002516 addInstr(env, X86Instr_Sse32FLo(op, arg, dst));
2517 return dst;
2518 }
2519
sewardj636ad762004-12-07 11:16:04 +00002520 case Iop_Recip64F0x2: op = Xsse_RCPF; goto do_64F0x2_unary;
2521 case Iop_RSqrt64F0x2: op = Xsse_RSQRTF; goto do_64F0x2_unary;
2522 case Iop_Sqrt64F0x2: op = Xsse_SQRTF; goto do_64F0x2_unary;
2523 do_64F0x2_unary:
2524 {
2525 /* A bit subtle. We have to copy the arg to the result
2526 register first, because actually doing the SSE scalar insn
2527 leaves the upper half of the destination register
2528 unchanged. Whereas the required semantics of these
2529 primops is that the upper half is simply copied in from the
2530 argument. */
2531 HReg arg = iselVecExpr(env, e->Iex.Unop.arg);
2532 HReg dst = newVRegV(env);
2533 addInstr(env, mk_vMOVsd_RR(arg, dst));
2534 addInstr(env, X86Instr_Sse64FLo(op, arg, dst));
2535 return dst;
2536 }
2537
sewardj129b3d92004-12-05 15:42:05 +00002538 case Iop_32Uto128: {
2539 HReg dst = newVRegV(env);
2540 X86AMode* esp0 = X86AMode_IR(0, hregX86_ESP());
2541 X86RMI* rmi = iselIntExpr_RMI(env, e->Iex.Unop.arg);
2542 addInstr(env, X86Instr_Push(rmi));
2543 addInstr(env, X86Instr_SseLdzLO(4, dst, esp0));
sewardj855f32d2004-12-05 21:22:38 +00002544 add_to_esp(env, 4);
sewardj129b3d92004-12-05 15:42:05 +00002545 return dst;
2546 }
2547
sewardj636ad762004-12-07 11:16:04 +00002548 case Iop_64Uto128: {
2549 HReg rHi, rLo;
2550 HReg dst = newVRegV(env);
2551 X86AMode* esp0 = X86AMode_IR(0, hregX86_ESP());
2552 iselInt64Expr(&rHi, &rLo, env, e->Iex.Unop.arg);
2553 addInstr(env, X86Instr_Push(X86RMI_Reg(rHi)));
2554 addInstr(env, X86Instr_Push(X86RMI_Reg(rLo)));
2555 addInstr(env, X86Instr_SseLdzLO(8, dst, esp0));
2556 add_to_esp(env, 8);
2557 return dst;
2558 }
2559
sewardj0bd7ce62004-12-05 02:47:40 +00002560 default:
2561 break;
2562 } /* switch (e->Iex.Unop.op) */
2563 } /* if (e->tag == Iex_Unop) */
2564
sewardjd08f2d72004-12-01 23:19:36 +00002565 if (e->tag == Iex_Binop) {
sewardj1e6ad742004-12-02 16:16:11 +00002566 switch (e->Iex.Binop.op) {
sewardj129b3d92004-12-05 15:42:05 +00002567
2568 case Iop_Set128lo32: {
2569 HReg dst = newVRegV(env);
2570 HReg srcV = iselVecExpr(env, e->Iex.Binop.arg1);
2571 HReg srcI = iselIntExpr_R(env, e->Iex.Binop.arg2);
2572 X86AMode* esp0 = X86AMode_IR(0, hregX86_ESP());
sewardj855f32d2004-12-05 21:22:38 +00002573 sub_from_esp(env, 16);
sewardj129b3d92004-12-05 15:42:05 +00002574 addInstr(env, X86Instr_SseLdSt(False/*store*/, srcV, esp0));
2575 addInstr(env, X86Instr_Alu32M(Xalu_MOV, X86RI_Reg(srcI), esp0));
2576 addInstr(env, X86Instr_SseLdSt(True/*load*/, dst, esp0));
sewardj855f32d2004-12-05 21:22:38 +00002577 add_to_esp(env, 16);
sewardj129b3d92004-12-05 15:42:05 +00002578 return dst;
2579 }
2580
sewardj008754b2004-12-08 14:37:10 +00002581 case Iop_Set128lo64: {
2582 HReg dst = newVRegV(env);
2583 HReg srcV = iselVecExpr(env, e->Iex.Binop.arg1);
2584 HReg srcIhi, srcIlo;
2585 X86AMode* esp0 = X86AMode_IR(0, hregX86_ESP());
2586 X86AMode* esp4 = advance4(esp0);
2587 iselInt64Expr(&srcIhi, &srcIlo, env, e->Iex.Binop.arg2);
2588 sub_from_esp(env, 16);
2589 addInstr(env, X86Instr_SseLdSt(False/*store*/, srcV, esp0));
2590 addInstr(env, X86Instr_Alu32M(Xalu_MOV, X86RI_Reg(srcIlo), esp0));
2591 addInstr(env, X86Instr_Alu32M(Xalu_MOV, X86RI_Reg(srcIhi), esp4));
2592 addInstr(env, X86Instr_SseLdSt(True/*load*/, dst, esp0));
2593 add_to_esp(env, 16);
2594 return dst;
2595 }
2596
sewardjd08f2d72004-12-01 23:19:36 +00002597 case Iop_64HLto128: {
2598 HReg r3, r2, r1, r0;
2599 X86AMode* esp0 = X86AMode_IR(0, hregX86_ESP());
2600 X86AMode* esp4 = advance4(esp0);
2601 X86AMode* esp8 = advance4(esp4);
2602 X86AMode* esp12 = advance4(esp8);
2603 HReg dst = newVRegV(env);
2604 /* do this via the stack (easy, convenient, etc) */
sewardj855f32d2004-12-05 21:22:38 +00002605 sub_from_esp(env, 16);
sewardjd08f2d72004-12-01 23:19:36 +00002606 /* Do the less significant 64 bits */
2607 iselInt64Expr(&r1, &r0, env, e->Iex.Binop.arg2);
2608 addInstr(env, X86Instr_Alu32M(Xalu_MOV, X86RI_Reg(r0), esp0));
2609 addInstr(env, X86Instr_Alu32M(Xalu_MOV, X86RI_Reg(r1), esp4));
2610 /* Do the more significant 64 bits */
2611 iselInt64Expr(&r3, &r2, env, e->Iex.Binop.arg1);
2612 addInstr(env, X86Instr_Alu32M(Xalu_MOV, X86RI_Reg(r2), esp8));
2613 addInstr(env, X86Instr_Alu32M(Xalu_MOV, X86RI_Reg(r3), esp12));
2614 /* Fetch result back from stack. */
2615 addInstr(env, X86Instr_SseLdSt(True/*load*/, dst, esp0));
sewardj855f32d2004-12-05 21:22:38 +00002616 add_to_esp(env, 16);
sewardjd08f2d72004-12-01 23:19:36 +00002617 return dst;
2618 }
sewardj1e6ad742004-12-02 16:16:11 +00002619
sewardj1e6ad742004-12-02 16:16:11 +00002620 case Iop_CmpEQ32Fx4: op = Xsse_CMPEQF; goto do_32Fx4;
2621 case Iop_CmpLT32Fx4: op = Xsse_CMPLTF; goto do_32Fx4;
2622 case Iop_CmpLE32Fx4: op = Xsse_CMPLEF; goto do_32Fx4;
2623 case Iop_Add32Fx4: op = Xsse_ADDF; goto do_32Fx4;
sewardj176a59c2004-12-03 20:08:31 +00002624 case Iop_Div32Fx4: op = Xsse_DIVF; goto do_32Fx4;
2625 case Iop_Max32Fx4: op = Xsse_MAXF; goto do_32Fx4;
2626 case Iop_Min32Fx4: op = Xsse_MINF; goto do_32Fx4;
sewardj9636b442004-12-04 01:38:37 +00002627 case Iop_Mul32Fx4: op = Xsse_MULF; goto do_32Fx4;
sewardjc1e7dfc2004-12-05 19:29:45 +00002628 case Iop_Sub32Fx4: op = Xsse_SUBF; goto do_32Fx4;
sewardj1e6ad742004-12-02 16:16:11 +00002629 do_32Fx4:
2630 {
2631 HReg argL = iselVecExpr(env, e->Iex.Binop.arg1);
2632 HReg argR = iselVecExpr(env, e->Iex.Binop.arg2);
2633 HReg dst = newVRegV(env);
2634 addInstr(env, mk_vMOVsd_RR(argL, dst));
2635 addInstr(env, X86Instr_Sse32Fx4(op, argR, dst));
2636 return dst;
2637 }
2638
sewardj636ad762004-12-07 11:16:04 +00002639 case Iop_CmpEQ64Fx2: op = Xsse_CMPEQF; goto do_64Fx2;
2640 case Iop_CmpLT64Fx2: op = Xsse_CMPLTF; goto do_64Fx2;
2641 case Iop_CmpLE64Fx2: op = Xsse_CMPLEF; goto do_64Fx2;
2642 case Iop_Add64Fx2: op = Xsse_ADDF; goto do_64Fx2;
2643 case Iop_Div64Fx2: op = Xsse_DIVF; goto do_64Fx2;
2644 case Iop_Max64Fx2: op = Xsse_MAXF; goto do_64Fx2;
2645 case Iop_Min64Fx2: op = Xsse_MINF; goto do_64Fx2;
2646 case Iop_Mul64Fx2: op = Xsse_MULF; goto do_64Fx2;
2647 case Iop_Sub64Fx2: op = Xsse_SUBF; goto do_64Fx2;
2648 do_64Fx2:
2649 {
2650 HReg argL = iselVecExpr(env, e->Iex.Binop.arg1);
2651 HReg argR = iselVecExpr(env, e->Iex.Binop.arg2);
2652 HReg dst = newVRegV(env);
2653 addInstr(env, mk_vMOVsd_RR(argL, dst));
2654 addInstr(env, X86Instr_Sse64Fx2(op, argR, dst));
2655 return dst;
2656 }
2657
sewardj1e6ad742004-12-02 16:16:11 +00002658 case Iop_CmpEQ32F0x4: op = Xsse_CMPEQF; goto do_32F0x4;
2659 case Iop_CmpLT32F0x4: op = Xsse_CMPLTF; goto do_32F0x4;
2660 case Iop_CmpLE32F0x4: op = Xsse_CMPLEF; goto do_32F0x4;
2661 case Iop_Add32F0x4: op = Xsse_ADDF; goto do_32F0x4;
sewardj176a59c2004-12-03 20:08:31 +00002662 case Iop_Div32F0x4: op = Xsse_DIVF; goto do_32F0x4;
2663 case Iop_Max32F0x4: op = Xsse_MAXF; goto do_32F0x4;
2664 case Iop_Min32F0x4: op = Xsse_MINF; goto do_32F0x4;
sewardj9636b442004-12-04 01:38:37 +00002665 case Iop_Mul32F0x4: op = Xsse_MULF; goto do_32F0x4;
sewardjc1e7dfc2004-12-05 19:29:45 +00002666 case Iop_Sub32F0x4: op = Xsse_SUBF; goto do_32F0x4;
sewardj1e6ad742004-12-02 16:16:11 +00002667 do_32F0x4: {
2668 HReg argL = iselVecExpr(env, e->Iex.Binop.arg1);
2669 HReg argR = iselVecExpr(env, e->Iex.Binop.arg2);
2670 HReg dst = newVRegV(env);
2671 addInstr(env, mk_vMOVsd_RR(argL, dst));
2672 addInstr(env, X86Instr_Sse32FLo(op, argR, dst));
2673 return dst;
2674 }
2675
sewardj636ad762004-12-07 11:16:04 +00002676 case Iop_CmpEQ64F0x2: op = Xsse_CMPEQF; goto do_64F0x2;
2677 case Iop_CmpLT64F0x2: op = Xsse_CMPLTF; goto do_64F0x2;
2678 case Iop_CmpLE64F0x2: op = Xsse_CMPLEF; goto do_64F0x2;
2679 case Iop_Add64F0x2: op = Xsse_ADDF; goto do_64F0x2;
2680 case Iop_Div64F0x2: op = Xsse_DIVF; goto do_64F0x2;
2681 case Iop_Max64F0x2: op = Xsse_MAXF; goto do_64F0x2;
2682 case Iop_Min64F0x2: op = Xsse_MINF; goto do_64F0x2;
2683 case Iop_Mul64F0x2: op = Xsse_MULF; goto do_64F0x2;
2684 case Iop_Sub64F0x2: op = Xsse_SUBF; goto do_64F0x2;
2685 do_64F0x2: {
2686 HReg argL = iselVecExpr(env, e->Iex.Binop.arg1);
2687 HReg argR = iselVecExpr(env, e->Iex.Binop.arg2);
2688 HReg dst = newVRegV(env);
2689 addInstr(env, mk_vMOVsd_RR(argL, dst));
2690 addInstr(env, X86Instr_Sse64FLo(op, argR, dst));
2691 return dst;
2692 }
2693
sewardj9e203592004-12-10 01:48:18 +00002694 case Iop_QNarrow32Sx4:
2695 op = Xsse_PACKSSD; arg1isEReg = True; goto do_SseReRg;
2696 case Iop_QNarrow16Sx8:
2697 op = Xsse_PACKSSW; arg1isEReg = True; goto do_SseReRg;
2698 case Iop_QNarrow16Ux8:
2699 op = Xsse_PACKUSW; arg1isEReg = True; goto do_SseReRg;
2700
2701 case Iop_InterleaveHI8x16:
2702 op = Xsse_UNPCKHB; arg1isEReg = True; goto do_SseReRg;
2703 case Iop_InterleaveHI16x8:
2704 op = Xsse_UNPCKHW; arg1isEReg = True; goto do_SseReRg;
2705 case Iop_InterleaveHI32x4:
2706 op = Xsse_UNPCKHD; arg1isEReg = True; goto do_SseReRg;
2707 case Iop_InterleaveHI64x2:
2708 op = Xsse_UNPCKHQ; arg1isEReg = True; goto do_SseReRg;
2709
2710 case Iop_InterleaveLO8x16:
2711 op = Xsse_UNPCKLB; arg1isEReg = True; goto do_SseReRg;
2712 case Iop_InterleaveLO16x8:
2713 op = Xsse_UNPCKLW; arg1isEReg = True; goto do_SseReRg;
2714 case Iop_InterleaveLO32x4:
2715 op = Xsse_UNPCKLD; arg1isEReg = True; goto do_SseReRg;
2716 case Iop_InterleaveLO64x2:
2717 op = Xsse_UNPCKLQ; arg1isEReg = True; goto do_SseReRg;
2718
2719 case Iop_And128: op = Xsse_AND; goto do_SseReRg;
2720 case Iop_Or128: op = Xsse_OR; goto do_SseReRg;
2721 case Iop_Xor128: op = Xsse_XOR; goto do_SseReRg;
sewardje5854d62004-12-09 03:44:34 +00002722 case Iop_Add8x16: op = Xsse_ADD8; goto do_SseReRg;
2723 case Iop_Add16x8: op = Xsse_ADD16; goto do_SseReRg;
2724 case Iop_Add32x4: op = Xsse_ADD32; goto do_SseReRg;
2725 case Iop_Add64x2: op = Xsse_ADD64; goto do_SseReRg;
2726 case Iop_QAdd8Sx16: op = Xsse_QADD8S; goto do_SseReRg;
2727 case Iop_QAdd16Sx8: op = Xsse_QADD16S; goto do_SseReRg;
2728 case Iop_QAdd8Ux16: op = Xsse_QADD8U; goto do_SseReRg;
2729 case Iop_QAdd16Ux8: op = Xsse_QADD16U; goto do_SseReRg;
2730 case Iop_Avg8Ux16: op = Xsse_AVG8U; goto do_SseReRg;
2731 case Iop_Avg16Ux8: op = Xsse_AVG16U; goto do_SseReRg;
2732 case Iop_CmpEQ8x16: op = Xsse_CMPEQ8; goto do_SseReRg;
2733 case Iop_CmpEQ16x8: op = Xsse_CMPEQ16; goto do_SseReRg;
2734 case Iop_CmpEQ32x4: op = Xsse_CMPEQ32; goto do_SseReRg;
2735 case Iop_CmpGT8Sx16: op = Xsse_CMPGT8S; goto do_SseReRg;
2736 case Iop_CmpGT16Sx8: op = Xsse_CMPGT16S; goto do_SseReRg;
2737 case Iop_CmpGT32Sx4: op = Xsse_CMPGT32S; goto do_SseReRg;
2738 case Iop_Max16Sx8: op = Xsse_MAX16S; goto do_SseReRg;
2739 case Iop_Max8Ux16: op = Xsse_MAX8U; goto do_SseReRg;
2740 case Iop_Min16Sx8: op = Xsse_MIN16S; goto do_SseReRg;
2741 case Iop_Min8Ux16: op = Xsse_MIN8U; goto do_SseReRg;
2742 case Iop_MulHi16Ux8: op = Xsse_MULHI16U; goto do_SseReRg;
2743 case Iop_MulHi16Sx8: op = Xsse_MULHI16S; goto do_SseReRg;
2744 case Iop_Mul16x8: op = Xsse_MUL16; goto do_SseReRg;
sewardjb9fa69b2004-12-09 23:25:14 +00002745 case Iop_Sub8x16: op = Xsse_SUB8; goto do_SseReRg;
2746 case Iop_Sub16x8: op = Xsse_SUB16; goto do_SseReRg;
2747 case Iop_Sub32x4: op = Xsse_SUB32; goto do_SseReRg;
2748 case Iop_Sub64x2: op = Xsse_SUB64; goto do_SseReRg;
2749 case Iop_QSub8Sx16: op = Xsse_QSUB8S; goto do_SseReRg;
2750 case Iop_QSub16Sx8: op = Xsse_QSUB16S; goto do_SseReRg;
2751 case Iop_QSub8Ux16: op = Xsse_QSUB8U; goto do_SseReRg;
2752 case Iop_QSub16Ux8: op = Xsse_QSUB16U; goto do_SseReRg;
sewardj164f9272004-12-09 00:39:32 +00002753 do_SseReRg: {
2754 HReg arg1 = iselVecExpr(env, e->Iex.Binop.arg1);
2755 HReg arg2 = iselVecExpr(env, e->Iex.Binop.arg2);
2756 HReg dst = newVRegV(env);
2757 if (arg1isEReg) {
2758 addInstr(env, mk_vMOVsd_RR(arg2, dst));
2759 addInstr(env, X86Instr_SseReRg(op, arg1, dst));
2760 } else {
2761 addInstr(env, mk_vMOVsd_RR(arg1, dst));
2762 addInstr(env, X86Instr_SseReRg(op, arg2, dst));
2763 }
2764 return dst;
2765 }
2766
sewardjb9fa69b2004-12-09 23:25:14 +00002767 case Iop_ShlN16x8: op = Xsse_SHL16; goto do_SseShift;
2768 case Iop_ShlN32x4: op = Xsse_SHL32; goto do_SseShift;
2769 case Iop_ShlN64x2: op = Xsse_SHL64; goto do_SseShift;
2770 case Iop_SarN16x8: op = Xsse_SAR16; goto do_SseShift;
2771 case Iop_SarN32x4: op = Xsse_SAR32; goto do_SseShift;
2772 case Iop_ShrN16x8: op = Xsse_SHR16; goto do_SseShift;
2773 case Iop_ShrN32x4: op = Xsse_SHR32; goto do_SseShift;
2774 case Iop_ShrN64x2: op = Xsse_SHR64; goto do_SseShift;
2775 do_SseShift: {
2776 HReg greg = iselVecExpr(env, e->Iex.Binop.arg1);
2777 X86RMI* rmi = iselIntExpr_RMI(env, e->Iex.Binop.arg2);
2778 X86AMode* esp0 = X86AMode_IR(0, hregX86_ESP());
2779 HReg ereg = newVRegV(env);
2780 HReg dst = newVRegV(env);
2781 addInstr(env, X86Instr_Push(X86RMI_Imm(0)));
2782 addInstr(env, X86Instr_Push(X86RMI_Imm(0)));
2783 addInstr(env, X86Instr_Push(X86RMI_Imm(0)));
2784 addInstr(env, X86Instr_Push(rmi));
2785 addInstr(env, X86Instr_SseLdSt(True/*load*/, ereg, esp0));
2786 addInstr(env, mk_vMOVsd_RR(greg, dst));
2787 addInstr(env, X86Instr_SseReRg(op, ereg, dst));
2788 add_to_esp(env, 16);
2789 return dst;
2790 }
2791
sewardjd08f2d72004-12-01 23:19:36 +00002792 default:
2793 break;
sewardj1e6ad742004-12-02 16:16:11 +00002794 } /* switch (e->Iex.Binop.op) */
sewardjd08f2d72004-12-01 23:19:36 +00002795 } /* if (e->tag == Iex_Binop) */
2796
sewardjb9fa69b2004-12-09 23:25:14 +00002797 if (e->tag == Iex_Mux0X) {
2798 HReg r8 = iselIntExpr_R(env, e->Iex.Mux0X.cond);
2799 HReg rX = iselVecExpr(env, e->Iex.Mux0X.exprX);
2800 HReg r0 = iselVecExpr(env, e->Iex.Mux0X.expr0);
2801 HReg dst = newVRegV(env);
2802 addInstr(env, mk_vMOVsd_RR(rX,dst));
2803 addInstr(env, X86Instr_Test32(X86RI_Imm(0xFF), X86RM_Reg(r8)));
2804 addInstr(env, X86Instr_SseCMov(Xcc_Z,r0,dst));
2805 return dst;
2806 }
2807
sewardjd08f2d72004-12-01 23:19:36 +00002808 ppIRExpr(e);
sewardj1e6ad742004-12-02 16:16:11 +00002809 vpanic("iselVecExpr_wrk");
sewardjd08f2d72004-12-01 23:19:36 +00002810}
2811
sewardj3196daf2004-08-13 00:18:58 +00002812
2813/*---------------------------------------------------------*/
sewardjc97096c2004-06-30 09:28:04 +00002814/*--- ISEL: Statements ---*/
2815/*---------------------------------------------------------*/
2816
sewardjf13a16a2004-07-05 17:10:14 +00002817static void iselStmt ( ISelEnv* env, IRStmt* stmt )
sewardjc97096c2004-06-30 09:28:04 +00002818{
sewardjf48ac192004-10-29 00:41:29 +00002819 if (vex_traceflags & VEX_TRACE_VCODE) {
2820 vex_printf("\n-- ");
sewardj1f40a0a2004-07-21 12:28:07 +00002821 ppIRStmt(stmt);
2822 vex_printf("\n");
2823 }
sewardj66f2f792004-06-30 16:37:16 +00002824
sewardjc97096c2004-06-30 09:28:04 +00002825 switch (stmt->tag) {
2826
sewardj60f4e3c2004-07-19 01:56:50 +00002827 /* --------- STORE --------- */
sewardjd9c2b792004-07-08 01:44:38 +00002828 case Ist_STle: {
sewardja58ea662004-08-15 03:12:41 +00002829 X86AMode* am;
sewardjd9c2b792004-07-08 01:44:38 +00002830 IRType tya = typeOfIRExpr(env->type_env, stmt->Ist.STle.addr);
2831 IRType tyd = typeOfIRExpr(env->type_env, stmt->Ist.STle.data);
2832 vassert(tya == Ity_I32);
sewardja58ea662004-08-15 03:12:41 +00002833 am = iselIntExpr_AMode(env, stmt->Ist.STle.addr);
sewardjd9c2b792004-07-08 01:44:38 +00002834 if (tyd == Ity_I32) {
sewardja58ea662004-08-15 03:12:41 +00002835 X86RI* ri = iselIntExpr_RI(env, stmt->Ist.STle.data);
sewardjd9c2b792004-07-08 01:44:38 +00002836 addInstr(env, X86Instr_Alu32M(Xalu_MOV,ri,am));
2837 return;
2838 }
sewardj60f4e3c2004-07-19 01:56:50 +00002839 if (tyd == Ity_I8 || tyd == Ity_I16) {
sewardja58ea662004-08-15 03:12:41 +00002840 HReg r = iselIntExpr_R(env, stmt->Ist.STle.data);
sewardj60f4e3c2004-07-19 01:56:50 +00002841 addInstr(env, X86Instr_Store(tyd==Ity_I8 ? 1 : 2,
2842 r,am));
sewardj443cd9d2004-07-18 23:06:45 +00002843 return;
2844 }
sewardja58ea662004-08-15 03:12:41 +00002845 if (tyd == Ity_F64) {
2846 HReg r = iselDblExpr(env, stmt->Ist.STle.data);
2847 addInstr(env, X86Instr_FpLdSt(False/*store*/, 8, r, am));
2848 return;
2849 }
sewardj89cd0932004-09-08 18:23:25 +00002850 if (tyd == Ity_F32) {
2851 HReg r = iselFltExpr(env, stmt->Ist.STle.data);
2852 addInstr(env, X86Instr_FpLdSt(False/*store*/, 4, r, am));
2853 return;
2854 }
sewardjcfded9a2004-09-09 11:44:16 +00002855 if (tyd == Ity_I64) {
2856 HReg vHi, vLo, rA;
sewardjd08f2d72004-12-01 23:19:36 +00002857 iselInt64Expr(&vHi, &vLo, env, stmt->Ist.STle.data);
sewardjcfded9a2004-09-09 11:44:16 +00002858 rA = iselIntExpr_R(env, stmt->Ist.STle.addr);
2859 addInstr(env, X86Instr_Alu32M(
2860 Xalu_MOV, X86RI_Reg(vLo), X86AMode_IR(0, rA)));
2861 addInstr(env, X86Instr_Alu32M(
2862 Xalu_MOV, X86RI_Reg(vHi), X86AMode_IR(4, rA)));
2863 return;
2864 }
sewardj9636b442004-12-04 01:38:37 +00002865 if (tyd == Ity_V128) {
2866 HReg r = iselVecExpr(env, stmt->Ist.STle.data);
2867 addInstr(env, X86Instr_SseLdSt(False/*store*/, r, am));
2868 return;
2869 }
sewardjd9c2b792004-07-08 01:44:38 +00002870 break;
sewardj79453082004-07-02 17:29:14 +00002871 }
2872
sewardj60f4e3c2004-07-19 01:56:50 +00002873 /* --------- PUT --------- */
sewardjd9c2b792004-07-08 01:44:38 +00002874 case Ist_Put: {
sewardj6d076362004-09-23 11:06:17 +00002875 IRType ty = typeOfIRExpr(env->type_env, stmt->Ist.Put.data);
sewardjd9c2b792004-07-08 01:44:38 +00002876 if (ty == Ity_I32) {
2877 /* We're going to write to memory, so compute the RHS into an
2878 X86RI. */
sewardj464efa42004-11-19 22:17:29 +00002879 X86RI* ri = iselIntExpr_RI(env, stmt->Ist.Put.data);
sewardjd9c2b792004-07-08 01:44:38 +00002880 addInstr(env,
2881 X86Instr_Alu32M(
2882 Xalu_MOV,
2883 ri,
2884 X86AMode_IR(stmt->Ist.Put.offset,hregX86_EBP())
2885 ));
2886 return;
2887 }
sewardj597b71b2004-07-19 02:51:12 +00002888 if (ty == Ity_I8 || ty == Ity_I16) {
sewardj6d076362004-09-23 11:06:17 +00002889 HReg r = iselIntExpr_R(env, stmt->Ist.Put.data);
sewardj443cd9d2004-07-18 23:06:45 +00002890 addInstr(env, X86Instr_Store(
sewardj597b71b2004-07-19 02:51:12 +00002891 ty==Ity_I8 ? 1 : 2,
2892 r,
sewardj443cd9d2004-07-18 23:06:45 +00002893 X86AMode_IR(stmt->Ist.Put.offset,
2894 hregX86_EBP())));
2895 return;
2896 }
sewardj464efa42004-11-19 22:17:29 +00002897 if (ty == Ity_I64) {
2898 HReg vHi, vLo;
2899 X86AMode* am = X86AMode_IR(stmt->Ist.Put.offset, hregX86_EBP());
2900 X86AMode* am4 = advance4(am);
sewardjd08f2d72004-12-01 23:19:36 +00002901 iselInt64Expr(&vHi, &vLo, env, stmt->Ist.Put.data);
sewardj464efa42004-11-19 22:17:29 +00002902 addInstr(env, X86Instr_Alu32M( Xalu_MOV, X86RI_Reg(vLo), am ));
2903 addInstr(env, X86Instr_Alu32M( Xalu_MOV, X86RI_Reg(vHi), am4 ));
2904 return;
2905 }
sewardjd08f2d72004-12-01 23:19:36 +00002906 if (ty == Ity_V128) {
2907 HReg vec = iselVecExpr(env, stmt->Ist.Put.data);
2908 X86AMode* am = X86AMode_IR(stmt->Ist.Put.offset, hregX86_EBP());
2909 addInstr(env, X86Instr_SseLdSt(False/*store*/, vec, am));
2910 return;
2911 }
sewardj4cb918d2004-12-03 19:43:31 +00002912 if (ty == Ity_F32) {
2913 HReg f32 = iselFltExpr(env, stmt->Ist.Put.data);
2914 X86AMode* am = X86AMode_IR(stmt->Ist.Put.offset, hregX86_EBP());
2915 set_FPU_rounding_default(env); /* paranoia */
2916 addInstr(env, X86Instr_FpLdSt( False/*store*/, 4, f32, am ));
2917 return;
2918 }
sewardjfd226452004-12-07 19:02:18 +00002919 if (ty == Ity_F64) {
2920 HReg f64 = iselDblExpr(env, stmt->Ist.Put.data);
2921 X86AMode* am = X86AMode_IR(stmt->Ist.Put.offset, hregX86_EBP());
2922 set_FPU_rounding_default(env); /* paranoia */
2923 addInstr(env, X86Instr_FpLdSt( False/*store*/, 8, f64, am ));
2924 return;
2925 }
sewardjd9c2b792004-07-08 01:44:38 +00002926 break;
2927 }
sewardje8e9d732004-07-16 21:03:45 +00002928
sewardj3196daf2004-08-13 00:18:58 +00002929 /* --------- Indexed PUT --------- */
2930 case Ist_PutI: {
sewardj2d3f77c2004-09-22 23:49:09 +00002931 X86AMode* am
2932 = genGuestArrayOffset(
2933 env, stmt->Ist.PutI.descr,
sewardjeeac8412004-11-02 00:26:55 +00002934 stmt->Ist.PutI.ix, stmt->Ist.PutI.bias );
sewardj3196daf2004-08-13 00:18:58 +00002935
sewardj2d3f77c2004-09-22 23:49:09 +00002936 IRType ty = typeOfIRExpr(env->type_env, stmt->Ist.PutI.data);
sewardj3196daf2004-08-13 00:18:58 +00002937 if (ty == Ity_F64) {
sewardj2d3f77c2004-09-22 23:49:09 +00002938 HReg val = iselDblExpr(env, stmt->Ist.PutI.data);
2939 addInstr(env, X86Instr_FpLdSt( False/*store*/, 8, val, am ));
sewardj3196daf2004-08-13 00:18:58 +00002940 return;
2941 }
sewardj3fc76d22004-08-31 11:47:54 +00002942 if (ty == Ity_I8) {
sewardj2d3f77c2004-09-22 23:49:09 +00002943 HReg r = iselIntExpr_R(env, stmt->Ist.PutI.data);
2944 addInstr(env, X86Instr_Store( 1, r, am ));
sewardj3fc76d22004-08-31 11:47:54 +00002945 return;
2946 }
sewardj218e29f2004-11-07 18:45:15 +00002947 if (ty == Ity_I64) {
2948 HReg rHi, rLo;
2949 X86AMode* am4 = advance4(am);
sewardjd08f2d72004-12-01 23:19:36 +00002950 iselInt64Expr(&rHi, &rLo, env, stmt->Ist.PutI.data);
sewardj218e29f2004-11-07 18:45:15 +00002951 addInstr(env, X86Instr_Alu32M( Xalu_MOV, X86RI_Reg(rLo), am ));
2952 addInstr(env, X86Instr_Alu32M( Xalu_MOV, X86RI_Reg(rHi), am4 ));
2953 return;
2954 }
sewardj3196daf2004-08-13 00:18:58 +00002955 break;
2956 }
2957
sewardj60f4e3c2004-07-19 01:56:50 +00002958 /* --------- TMP --------- */
sewardjd9c2b792004-07-08 01:44:38 +00002959 case Ist_Tmp: {
2960 IRTemp tmp = stmt->Ist.Tmp.tmp;
sewardj17442fe2004-09-20 14:54:28 +00002961 IRType ty = typeOfIRTemp(env->type_env, tmp);
sewardj4042c7e2004-07-18 01:28:30 +00002962 if (ty == Ity_I32 || ty == Ity_I16 || ty == Ity_I8) {
sewardj6d076362004-09-23 11:06:17 +00002963 X86RMI* rmi = iselIntExpr_RMI(env, stmt->Ist.Tmp.data);
sewardjd9c2b792004-07-08 01:44:38 +00002964 HReg dst = lookupIRTemp(env, tmp);
2965 addInstr(env, X86Instr_Alu32R(Xalu_MOV,rmi,dst));
2966 return;
2967 }
sewardj597b71b2004-07-19 02:51:12 +00002968 if (ty == Ity_I64) {
2969 HReg rHi, rLo, dstHi, dstLo;
sewardjd08f2d72004-12-01 23:19:36 +00002970 iselInt64Expr(&rHi,&rLo, env, stmt->Ist.Tmp.data);
sewardj597b71b2004-07-19 02:51:12 +00002971 lookupIRTemp64( &dstHi, &dstLo, env, tmp);
sewardjd08f2d72004-12-01 23:19:36 +00002972 addInstr(env, mk_iMOVsd_RR(rHi,dstHi) );
2973 addInstr(env, mk_iMOVsd_RR(rLo,dstLo) );
sewardj597b71b2004-07-19 02:51:12 +00002974 return;
2975 }
sewardjba999312004-11-15 15:21:17 +00002976 if (ty == Ity_I1) {
sewardj6d076362004-09-23 11:06:17 +00002977 X86CondCode cond = iselCondCode(env, stmt->Ist.Tmp.data);
sewardjd7cb8532004-08-17 23:59:23 +00002978 HReg dst = lookupIRTemp(env, tmp);
2979 addInstr(env, X86Instr_Set32(cond, dst));
2980 return;
2981 }
sewardjbb53f8c2004-08-14 11:50:01 +00002982 if (ty == Ity_F64) {
2983 HReg dst = lookupIRTemp(env, tmp);
sewardj6d076362004-09-23 11:06:17 +00002984 HReg src = iselDblExpr(env, stmt->Ist.Tmp.data);
sewardjbb53f8c2004-08-14 11:50:01 +00002985 addInstr(env, X86Instr_FpUnary(Xfp_MOV,src,dst));
2986 return;
2987 }
sewardj4a8b2a52004-10-13 20:45:25 +00002988 if (ty == Ity_F32) {
2989 HReg dst = lookupIRTemp(env, tmp);
2990 HReg src = iselFltExpr(env, stmt->Ist.Tmp.data);
2991 addInstr(env, X86Instr_FpUnary(Xfp_MOV,src,dst));
2992 return;
2993 }
sewardjd08f2d72004-12-01 23:19:36 +00002994 if (ty == Ity_V128) {
2995 HReg dst = lookupIRTemp(env, tmp);
2996 HReg src = iselVecExpr(env, stmt->Ist.Tmp.data);
2997 addInstr(env, mk_vMOVsd_RR(src,dst));
2998 return;
2999 }
sewardjd9c2b792004-07-08 01:44:38 +00003000 break;
3001 }
sewardj79453082004-07-02 17:29:14 +00003002
sewardj17442fe2004-09-20 14:54:28 +00003003 /* --------- Call to DIRTY helper --------- */
3004 case Ist_Dirty: {
sewardj17442fe2004-09-20 14:54:28 +00003005 IRType retty;
3006 IRDirty* d = stmt->Ist.Dirty.details;
sewardj77352542004-10-30 20:39:01 +00003007 Bool passBBP = False;
sewardj17442fe2004-09-20 14:54:28 +00003008
sewardjc5fc7aa2004-10-27 23:00:55 +00003009 if (d->nFxState == 0)
3010 vassert(!d->needsBBP);
sewardj77352542004-10-30 20:39:01 +00003011 passBBP = d->nFxState > 0 && d->needsBBP;
sewardj7cb49d72004-10-24 22:31:25 +00003012
sewardj77352542004-10-30 20:39:01 +00003013 /* Marshal args, do the call, clear stack. */
sewardj4b861de2004-11-03 15:24:42 +00003014 doHelperCall( env, passBBP, d->guard, d->cee, d->args );
sewardj17442fe2004-09-20 14:54:28 +00003015
3016 /* Now figure out what to do with the returned value, if any. */
sewardj92d168d2004-11-15 14:22:12 +00003017 if (d->tmp == IRTemp_INVALID)
sewardj17442fe2004-09-20 14:54:28 +00003018 /* No return value. Nothing to do. */
3019 return;
3020
3021 retty = typeOfIRTemp(env->type_env, d->tmp);
3022 if (retty == Ity_I64) {
3023 HReg dstHi, dstLo;
3024 /* The returned value is in %edx:%eax. Park it in the
3025 register-pair associated with tmp. */
3026 lookupIRTemp64( &dstHi, &dstLo, env, d->tmp);
sewardjd08f2d72004-12-01 23:19:36 +00003027 addInstr(env, mk_iMOVsd_RR(hregX86_EDX(),dstHi) );
3028 addInstr(env, mk_iMOVsd_RR(hregX86_EAX(),dstLo) );
sewardj17442fe2004-09-20 14:54:28 +00003029 return;
3030 }
sewardj415d9352004-11-04 15:20:15 +00003031 if (retty == Ity_I32 || retty == Ity_I16 || retty == Ity_I8) {
sewardj4b861de2004-11-03 15:24:42 +00003032 /* The returned value is in %eax. Park it in the register
3033 associated with tmp. */
3034 HReg dst = lookupIRTemp(env, d->tmp);
sewardjd08f2d72004-12-01 23:19:36 +00003035 addInstr(env, mk_iMOVsd_RR(hregX86_EAX(),dst) );
sewardj4b861de2004-11-03 15:24:42 +00003036 return;
3037 }
sewardj17442fe2004-09-20 14:54:28 +00003038 break;
3039 }
3040
sewardj60f4e3c2004-07-19 01:56:50 +00003041 /* --------- EXIT --------- */
sewardje8e9d732004-07-16 21:03:45 +00003042 case Ist_Exit: {
sewardj2e56f9f2004-07-24 01:24:38 +00003043 X86RI* dst;
3044 X86CondCode cc;
3045 if (stmt->Ist.Exit.dst->tag != Ico_U32)
3046 vpanic("isel_x86: Ist_Exit: dst is not a 32-bit value");
3047 dst = iselIntExpr_RI(env, IRExpr_Const(stmt->Ist.Exit.dst));
sewardj0276d4b2004-11-15 15:30:21 +00003048 cc = iselCondCode(env,stmt->Ist.Exit.guard);
sewardj893aada2004-11-29 19:57:54 +00003049 addInstr(env, X86Instr_Goto(stmt->Ist.Exit.jk, cc, dst));
sewardj2e56f9f2004-07-24 01:24:38 +00003050 return;
sewardje8e9d732004-07-16 21:03:45 +00003051 }
3052
sewardjc97096c2004-06-30 09:28:04 +00003053 default: break;
3054 }
sewardj35421a32004-07-05 13:12:34 +00003055 ppIRStmt(stmt);
3056 vpanic("iselStmt");
sewardjc97096c2004-06-30 09:28:04 +00003057}
3058
3059
3060/*---------------------------------------------------------*/
3061/*--- ISEL: Basic block terminators (Nexts) ---*/
3062/*---------------------------------------------------------*/
3063
sewardje539a402004-07-14 18:24:17 +00003064static void iselNext ( ISelEnv* env, IRExpr* next, IRJumpKind jk )
sewardjc97096c2004-06-30 09:28:04 +00003065{
sewardje8e9d732004-07-16 21:03:45 +00003066 X86RI* ri;
sewardjf48ac192004-10-29 00:41:29 +00003067 if (vex_traceflags & VEX_TRACE_VCODE) {
3068 vex_printf("\n-- goto {");
sewardj750f4072004-07-26 22:39:11 +00003069 ppIRJumpKind(jk);
3070 vex_printf("} ");
sewardj1f40a0a2004-07-21 12:28:07 +00003071 ppIRExpr(next);
3072 vex_printf("\n");
3073 }
sewardje8e9d732004-07-16 21:03:45 +00003074 ri = iselIntExpr_RI(env, next);
sewardj750f4072004-07-26 22:39:11 +00003075 addInstr(env, X86Instr_Goto(jk, Xcc_ALWAYS,ri));
sewardjc97096c2004-06-30 09:28:04 +00003076}
3077
3078
3079/*---------------------------------------------------------*/
3080/*--- Insn selector top-level ---*/
3081/*---------------------------------------------------------*/
3082
sewardj194d54a2004-07-03 19:08:18 +00003083/* Translate an entire BB to x86 code. */
3084
sewardj8ea867b2004-10-30 19:03:02 +00003085HInstrArray* iselBB_X86 ( IRBB* bb )
sewardjc97096c2004-06-30 09:28:04 +00003086{
sewardj597b71b2004-07-19 02:51:12 +00003087 Int i, j;
sewardje8e9d732004-07-16 21:03:45 +00003088 HReg hreg, hregHI;
sewardjc97096c2004-06-30 09:28:04 +00003089
3090 /* Make up an initial environment to use. */
sewardj35421a32004-07-05 13:12:34 +00003091 ISelEnv* env = LibVEX_Alloc(sizeof(ISelEnv));
sewardj194d54a2004-07-03 19:08:18 +00003092 env->vreg_ctr = 0;
sewardjc97096c2004-06-30 09:28:04 +00003093
3094 /* Set up output code array. */
sewardj2cd80dc2004-07-02 15:20:40 +00003095 env->code = newHInstrArray();
sewardjc97096c2004-06-30 09:28:04 +00003096
3097 /* Copy BB's type env. */
3098 env->type_env = bb->tyenv;
3099
3100 /* Make up an IRTemp -> virtual HReg mapping. This doesn't
3101 change as we go along. */
sewardje539a402004-07-14 18:24:17 +00003102 env->n_vregmap = bb->tyenv->types_used;
3103 env->vregmap = LibVEX_Alloc(env->n_vregmap * sizeof(HReg));
sewardje8e9d732004-07-16 21:03:45 +00003104 env->vregmapHI = LibVEX_Alloc(env->n_vregmap * sizeof(HReg));
sewardjc97096c2004-06-30 09:28:04 +00003105
3106 /* For each IR temporary, allocate a suitably-kinded virtual
3107 register. */
sewardj597b71b2004-07-19 02:51:12 +00003108 j = 0;
sewardjc97096c2004-06-30 09:28:04 +00003109 for (i = 0; i < env->n_vregmap; i++) {
sewardje8e9d732004-07-16 21:03:45 +00003110 hregHI = hreg = INVALID_HREG;
sewardje539a402004-07-14 18:24:17 +00003111 switch (bb->tyenv->types[i]) {
sewardjba999312004-11-15 15:21:17 +00003112 case Ity_I1:
sewardje8e9d732004-07-16 21:03:45 +00003113 case Ity_I8:
sewardj4042c7e2004-07-18 01:28:30 +00003114 case Ity_I16:
sewardjd08f2d72004-12-01 23:19:36 +00003115 case Ity_I32: hreg = mkHReg(j++, HRcInt32, True); break;
3116 case Ity_I64: hreg = mkHReg(j++, HRcInt32, True);
3117 hregHI = mkHReg(j++, HRcInt32, True); break;
sewardj89cd0932004-09-08 18:23:25 +00003118 case Ity_F32:
sewardjd08f2d72004-12-01 23:19:36 +00003119 case Ity_F64: hreg = mkHReg(j++, HRcFlt64, True); break;
3120 case Ity_V128: hreg = mkHReg(j++, HRcVec128, True); break;
sewardje8e9d732004-07-16 21:03:45 +00003121 default: ppIRType(bb->tyenv->types[i]);
3122 vpanic("iselBB: IRTemp type");
sewardjc97096c2004-06-30 09:28:04 +00003123 }
sewardje8e9d732004-07-16 21:03:45 +00003124 env->vregmap[i] = hreg;
3125 env->vregmapHI[i] = hregHI;
sewardjc97096c2004-06-30 09:28:04 +00003126 }
sewardje322b0a2004-07-28 07:12:30 +00003127 env->vreg_ctr = j;
sewardjc97096c2004-06-30 09:28:04 +00003128
3129 /* Ok, finally we can iterate over the statements. */
sewardjd7cb8532004-08-17 23:59:23 +00003130 for (i = 0; i < bb->stmts_used; i++)
sewardj39e3f242004-08-18 16:54:52 +00003131 if (bb->stmts[i])
3132 iselStmt(env,bb->stmts[i]);
sewardjc97096c2004-06-30 09:28:04 +00003133
sewardje539a402004-07-14 18:24:17 +00003134 iselNext(env,bb->next,bb->jumpkind);
sewardj2cd80dc2004-07-02 15:20:40 +00003135
sewardj194d54a2004-07-03 19:08:18 +00003136 /* record the number of vregs we used. */
3137 env->code->n_vregs = env->vreg_ctr;
sewardj2cd80dc2004-07-02 15:20:40 +00003138 return env->code;
sewardjc97096c2004-06-30 09:28:04 +00003139}
sewardj887a11a2004-07-05 17:26:47 +00003140
3141
3142/*---------------------------------------------------------------*/
sewardjc0ee2ed2004-07-27 10:29:41 +00003143/*--- end host-x86/isel.c ---*/
sewardj887a11a2004-07-05 17:26:47 +00003144/*---------------------------------------------------------------*/