1ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------------*/
3ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- begin                                   host_x86_isel.c ---*/
4ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------------*/
5ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*
7ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   This file is part of Valgrind, a dynamic binary instrumentation
8ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   framework.
9ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   Copyright (C) 2004-2011 OpenWorks LLP
11ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      info@open-works.net
12ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   This program is free software; you can redistribute it and/or
14ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   modify it under the terms of the GNU General Public License as
15ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   published by the Free Software Foundation; either version 2 of the
16ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   License, or (at your option) any later version.
17ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
18ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   This program is distributed in the hope that it will be useful, but
19ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   WITHOUT ANY WARRANTY; without even the implied warranty of
20ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
21ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   General Public License for more details.
22ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
23ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   You should have received a copy of the GNU General Public License
24ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   along with this program; if not, write to the Free Software
25ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
26ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   02110-1301, USA.
27ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
28ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   The GNU General Public License is contained in the file COPYING.
29ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
30ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Neither the names of the U.S. Department of Energy nor the
31ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   University of California nor the names of its contributors may be
32ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   used to endorse or promote products derived from this software
33ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   without prior written permission.
34ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
35ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
36ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "libvex_basictypes.h"
37ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "libvex_ir.h"
38ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "libvex.h"
39ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
40ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "ir_match.h"
41ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "main_util.h"
42ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "main_globals.h"
43ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "host_generic_regs.h"
44ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "host_generic_simd64.h"
45b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#include "host_generic_simd128.h"
46ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "host_x86_defs.h"
47ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
48ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* TODO 21 Apr 2005:
49ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
50ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   -- (Really an assembler issue) don't emit CMov32 as a cmov
51ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      insn, since that's expensive on P4 and conditional branch
52ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      is cheaper if (as we expect) the condition is highly predictable
53ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
54ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   -- preserve xmm registers across function calls (by declaring them
55ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      as trashed by call insns)
56ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
57ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   -- preserve x87 ST stack discipline across function calls.  Sigh.
58ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
59ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   -- Check doHelperCall: if a call is conditional, we cannot safely
60ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      compute any regparm args directly to registers.  Hence, the
61ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      fast-regparm marshalling should be restricted to unconditional
62ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      calls only.
63ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
64ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
65ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------*/
66ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- x87 control word stuff                            ---*/
67ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------*/
68ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
69ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Vex-generated code expects to run with the FPU set as follows: all
70ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   exceptions masked, round-to-nearest, precision = 53 bits.  This
71ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   corresponds to a FPU control word value of 0x027F.
72ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
73ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Similarly the SSE control word (%mxcsr) should be 0x1F80.
74ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
75ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   %fpucw and %mxcsr should have these values on entry to
76ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Vex-generated code, and should those values should be
77ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   unchanged at exit.
78ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
79ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
80ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define DEFAULT_FPUCW 0x027F
81ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
82ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* debugging only, do not use */
83ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* define DEFAULT_FPUCW 0x037F */
84ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
85ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
86ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------*/
87ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- misc helpers                                      ---*/
88ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------*/
89ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
90ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* These are duplicated in guest-x86/toIR.c */
91ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRExpr* unop ( IROp op, IRExpr* a )
92ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
93ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return IRExpr_Unop(op, a);
94ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
95ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
96ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRExpr* binop ( IROp op, IRExpr* a1, IRExpr* a2 )
97ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
98ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return IRExpr_Binop(op, a1, a2);
99ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRExpr* bind ( Int binder )
102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return IRExpr_Binder(binder);
104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool isZeroU8 ( IRExpr* e )
107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return e->tag == Iex_Const
109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          && e->Iex.Const.con->tag == Ico_U8
110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          && e->Iex.Const.con->Ico.U8 == 0;
111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool isZeroU32 ( IRExpr* e )
114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return e->tag == Iex_Const
116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          && e->Iex.Const.con->tag == Ico_U32
117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          && e->Iex.Const.con->Ico.U32 == 0;
118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool isZeroU64 ( IRExpr* e )
121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return e->tag == Iex_Const
123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          && e->Iex.Const.con->tag == Ico_U64
124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          && e->Iex.Const.con->Ico.U64 == 0ULL;
125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------*/
129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- ISelEnv                                           ---*/
130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------*/
131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* This carries around:
133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   - A mapping from IRTemp to IRType, giving the type of any IRTemp we
135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     might encounter.  This is computed before insn selection starts,
136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     and does not change.
137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   - A mapping from IRTemp to HReg.  This tells the insn selector
139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     which virtual register(s) are associated with each IRTemp
140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     temporary.  This is computed before insn selection starts, and
141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     does not change.  We expect this mapping to map precisely the
142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     same set of IRTemps as the type mapping does.
143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        - vregmap   holds the primary register for the IRTemp.
145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        - vregmapHI is only used for 64-bit integer-typed
146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             IRTemps.  It holds the identity of a second
147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             32-bit virtual HReg, which holds the high half
148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             of the value.
149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   - The code array, that is, the insns selected so far.
151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   - A counter, for generating new virtual registers.
153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   - The host subarchitecture we are selecting insns for.
155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     This is set at the start and does not change.
156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Note, this is all host-independent.  */
158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef
160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   struct {
161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTypeEnv*   type_env;
162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HReg*        vregmap;
164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HReg*        vregmapHI;
165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Int          n_vregmap;
166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HInstrArray* code;
168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Int          vreg_ctr;
170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt         hwcaps;
172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ISelEnv;
174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic HReg lookupIRTemp ( ISelEnv* env, IRTemp tmp )
177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(tmp >= 0);
179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(tmp < env->n_vregmap);
180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return env->vregmap[tmp];
181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void lookupIRTemp64 ( HReg* vrHI, HReg* vrLO, ISelEnv* env, IRTemp tmp )
184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(tmp >= 0);
186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(tmp < env->n_vregmap);
187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(env->vregmapHI[tmp] != INVALID_HREG);
188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   *vrLO = env->vregmap[tmp];
189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   *vrHI = env->vregmapHI[tmp];
190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void addInstr ( ISelEnv* env, X86Instr* instr )
193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   addHInstr(env->code, instr);
195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (vex_traceflags & VEX_TRACE_VCODE) {
196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ppX86Instr(instr, False);
197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vex_printf("\n");
198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic HReg newVRegI ( ISelEnv* env )
202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   HReg reg = mkHReg(env->vreg_ctr, HRcInt32, True/*virtual reg*/);
204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   env->vreg_ctr++;
205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return reg;
206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic HReg newVRegF ( ISelEnv* env )
209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   HReg reg = mkHReg(env->vreg_ctr, HRcFlt64, True/*virtual reg*/);
211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   env->vreg_ctr++;
212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return reg;
213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic HReg newVRegV ( ISelEnv* env )
216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   HReg reg = mkHReg(env->vreg_ctr, HRcVec128, True/*virtual reg*/);
218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   env->vreg_ctr++;
219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return reg;
220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------*/
224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- ISEL: Forward declarations                        ---*/
225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------*/
226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* These are organised as iselXXX and iselXXX_wrk pairs.  The
228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   iselXXX_wrk do the real work, but are not to be called directly.
229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   For each XXX, iselXXX calls its iselXXX_wrk counterpart, then
230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   checks that all returned registers are virtual.  You should not
231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   call the _wrk version directly.
232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic X86RMI*     iselIntExpr_RMI_wrk ( ISelEnv* env, IRExpr* e );
234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic X86RMI*     iselIntExpr_RMI     ( ISelEnv* env, IRExpr* e );
235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic X86RI*      iselIntExpr_RI_wrk ( ISelEnv* env, IRExpr* e );
237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic X86RI*      iselIntExpr_RI     ( ISelEnv* env, IRExpr* e );
238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic X86RM*      iselIntExpr_RM_wrk ( ISelEnv* env, IRExpr* e );
240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic X86RM*      iselIntExpr_RM     ( ISelEnv* env, IRExpr* e );
241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic HReg        iselIntExpr_R_wrk ( ISelEnv* env, IRExpr* e );
243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic HReg        iselIntExpr_R     ( ISelEnv* env, IRExpr* e );
244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic X86AMode*   iselIntExpr_AMode_wrk ( ISelEnv* env, IRExpr* e );
246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic X86AMode*   iselIntExpr_AMode     ( ISelEnv* env, IRExpr* e );
247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void        iselInt64Expr_wrk ( HReg* rHi, HReg* rLo,
249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                       ISelEnv* env, IRExpr* e );
250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void        iselInt64Expr     ( HReg* rHi, HReg* rLo,
251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                       ISelEnv* env, IRExpr* e );
252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic X86CondCode iselCondCode_wrk ( ISelEnv* env, IRExpr* e );
254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic X86CondCode iselCondCode     ( ISelEnv* env, IRExpr* e );
255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic HReg        iselDblExpr_wrk ( ISelEnv* env, IRExpr* e );
257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic HReg        iselDblExpr     ( ISelEnv* env, IRExpr* e );
258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic HReg        iselFltExpr_wrk ( ISelEnv* env, IRExpr* e );
260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic HReg        iselFltExpr     ( ISelEnv* env, IRExpr* e );
261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic HReg        iselVecExpr_wrk ( ISelEnv* env, IRExpr* e );
263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic HReg        iselVecExpr     ( ISelEnv* env, IRExpr* e );
264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------*/
267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- ISEL: Misc helpers                                ---*/
268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------*/
269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Make a int reg-reg move. */
271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic X86Instr* mk_iMOVsd_RR ( HReg src, HReg dst )
273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(hregClass(src) == HRcInt32);
275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(hregClass(dst) == HRcInt32);
276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return X86Instr_Alu32R(Xalu_MOV, X86RMI_Reg(src), dst);
277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Make a vector reg-reg move. */
281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic X86Instr* mk_vMOVsd_RR ( HReg src, HReg dst )
283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(hregClass(src) == HRcVec128);
285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(hregClass(dst) == HRcVec128);
286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return X86Instr_SseReRg(Xsse_MOV, src, dst);
287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Advance/retreat %esp by n. */
290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void add_to_esp ( ISelEnv* env, Int n )
292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(n > 0 && n < 256 && (n%4) == 0);
294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   addInstr(env,
295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            X86Instr_Alu32R(Xalu_ADD, X86RMI_Imm(n), hregX86_ESP()));
296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void sub_from_esp ( ISelEnv* env, Int n )
299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(n > 0 && n < 256 && (n%4) == 0);
301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   addInstr(env,
302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            X86Instr_Alu32R(Xalu_SUB, X86RMI_Imm(n), hregX86_ESP()));
303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Given an amode, return one which references 4 bytes further
307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   along. */
308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic X86AMode* advance4 ( X86AMode* am )
310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   X86AMode* am4 = dopyX86AMode(am);
312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (am4->tag) {
313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xam_IRRS:
314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         am4->Xam.IRRS.imm += 4; break;
315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xam_IR:
316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         am4->Xam.IR.imm += 4; break;
317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vpanic("advance4(x86,host)");
319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return am4;
321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Push an arg onto the host stack, in preparation for a call to a
325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   helper function of some kind.  Returns the number of 32-bit words
326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   pushed. */
327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Int pushArg ( ISelEnv* env, IRExpr* arg )
329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRType arg_ty = typeOfIRExpr(env->type_env, arg);
331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (arg_ty == Ity_I32) {
332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env, X86Instr_Push(iselIntExpr_RMI(env, arg)));
333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return 1;
334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else
335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (arg_ty == Ity_I64) {
336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HReg rHi, rLo;
337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      iselInt64Expr(&rHi, &rLo, env, arg);
338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env, X86Instr_Push(X86RMI_Reg(rHi)));
339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env, X86Instr_Push(X86RMI_Reg(rLo)));
340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return 2;
341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ppIRExpr(arg);
343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vpanic("pushArg(x86): can't handle arg of this type");
344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Complete the call to a helper function, by calling the
348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   helper and clearing the args off the stack. */
349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid callHelperAndClearArgs ( ISelEnv* env, X86CondCode cc,
352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              IRCallee* cee, Int n_arg_ws )
353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Complication.  Need to decide which reg to use as the fn address
355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      pointer, in a way that doesn't trash regparm-passed
356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      parameters. */
357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(sizeof(void*) == 4);
358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   addInstr(env, X86Instr_Call( cc, toUInt(Ptr_to_ULong(cee->addr)),
360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                    cee->regparms));
361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (n_arg_ws > 0)
362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      add_to_esp(env, 4*n_arg_ws);
363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Used only in doHelperCall.  See big comment in doHelperCall re
367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   handling of regparm args.  This function figures out whether
368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   evaluation of an expression might require use of a fixed register.
369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   If in doubt return True (safe but suboptimal).
370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownBool mightRequireFixedRegs ( IRExpr* e )
373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (e->tag) {
375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iex_RdTmp: case Iex_Const: case Iex_Get:
376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return False;
377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return True;
379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Do a complete function call.  guard is a Ity_Bit expression
384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   indicating whether or not the call happens.  If guard==NULL, the
385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   call is unconditional. */
386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid doHelperCall ( ISelEnv* env,
389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    Bool passBBP,
390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    IRExpr* guard, IRCallee* cee, IRExpr** args )
391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   X86CondCode cc;
393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   HReg        argregs[3];
394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   HReg        tmpregs[3];
395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Bool        danger;
396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int         not_done_yet, n_args, n_arg_ws, stack_limit,
397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               i, argreg, argregX;
398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Marshal args for a call, do the call, and clear the stack.
400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Complexities to consider:
401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      * if passBBP is True, %ebp (the baseblock pointer) is to be
403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        passed as the first arg.
404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      * If the callee claims regparmness of 1, 2 or 3, we must pass the
406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        first 1, 2 or 3 args in registers (EAX, EDX, and ECX
407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        respectively).  To keep things relatively simple, only args of
408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        type I32 may be passed as regparms -- just bomb out if anything
409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        else turns up.  Clearly this depends on the front ends not
410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        trying to pass any other types as regparms.
411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   */
412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* 16 Nov 2004: the regparm handling is complicated by the
414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      following problem.
415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Consider a call two a function with two regparm parameters:
417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      f(e1,e2).  We need to compute e1 into %eax and e2 into %edx.
418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Suppose code is first generated to compute e1 into %eax.  Then,
419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      code is generated to compute e2 into %edx.  Unfortunately, if
420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      the latter code sequence uses %eax, it will trash the value of
421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      e1 computed by the former sequence.  This could happen if (for
422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      example) e2 itself involved a function call.  In the code below,
423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      args are evaluated right-to-left, not left-to-right, but the
424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      principle and the problem are the same.
425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      One solution is to compute all regparm-bound args into vregs
427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      first, and once they are all done, move them to the relevant
428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      real regs.  This always gives correct code, but it also gives
429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      a bunch of vreg-to-rreg moves which are usually redundant but
430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      are hard for the register allocator to get rid of.
431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      A compromise is to first examine all regparm'd argument
433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      expressions.  If they are all so simple that it is clear
434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      they will be evaluated without use of any fixed registers,
435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      use the old compute-directly-to-fixed-target scheme.  If not,
436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      be safe and use the via-vregs scheme.
437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Note this requires being able to examine an expression and
439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      determine whether or not evaluation of it might use a fixed
440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      register.  That requires knowledge of how the rest of this
441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      insn selector works.  Currently just the following 3 are
442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      regarded as safe -- hopefully they cover the majority of
443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      arguments in practice: IRExpr_Tmp IRExpr_Const IRExpr_Get.
444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   */
445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(cee->regparms >= 0 && cee->regparms <= 3);
446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   n_args = n_arg_ws = 0;
448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   while (args[n_args]) n_args++;
449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   not_done_yet = n_args;
451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (passBBP)
452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      not_done_yet++;
453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   stack_limit = cee->regparms;
455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (cee->regparms > 0 && passBBP) stack_limit--;
456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* ------ BEGIN marshall all arguments ------ */
458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Push (R to L) the stack-passed args, [n_args-1 .. stack_limit] */
460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (i = n_args-1; i >= stack_limit; i--) {
461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      n_arg_ws += pushArg(env, args[i]);
462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      not_done_yet--;
463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* args [stack_limit-1 .. 0] and possibly %ebp are to be passed in
466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      registers. */
467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (cee->regparms > 0) {
469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* ------ BEGIN deal with regparms ------ */
471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* deal with regparms, not forgetting %ebp if needed. */
473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      argregs[0] = hregX86_EAX();
474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      argregs[1] = hregX86_EDX();
475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      argregs[2] = hregX86_ECX();
476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      tmpregs[0] = tmpregs[1] = tmpregs[2] = INVALID_HREG;
477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      argreg = cee->regparms;
479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* In keeping with big comment above, detect potential danger
481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         and use the via-vregs scheme if needed. */
482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      danger = False;
483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      for (i = stack_limit-1; i >= 0; i--) {
484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (mightRequireFixedRegs(args[i])) {
485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            danger = True;
486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (danger) {
491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Move via temporaries */
493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         argregX = argreg;
494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         for (i = stack_limit-1; i >= 0; i--) {
495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (0) {
497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               vex_printf("x86 host: register param is complex: ");
498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               ppIRExpr(args[i]);
499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               vex_printf("\n");
500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            argreg--;
503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vassert(argreg >= 0);
504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vassert(typeOfIRExpr(env->type_env, args[i]) == Ity_I32);
505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            tmpregs[argreg] = iselIntExpr_R(env, args[i]);
506ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            not_done_yet--;
507ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
508ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         for (i = stack_limit-1; i >= 0; i--) {
509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            argregX--;
510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vassert(argregX >= 0);
511ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr( env, mk_iMOVsd_RR( tmpregs[argregX], argregs[argregX] ) );
512ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
513ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
514ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else {
515ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* It's safe to compute all regparm args directly into their
516ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            target registers. */
517ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         for (i = stack_limit-1; i >= 0; i--) {
518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            argreg--;
519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vassert(argreg >= 0);
520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vassert(typeOfIRExpr(env->type_env, args[i]) == Ity_I32);
521ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, X86Instr_Alu32R(Xalu_MOV,
522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                          iselIntExpr_RMI(env, args[i]),
523ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                          argregs[argreg]));
524ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            not_done_yet--;
525ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
526ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
527ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
528ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
529ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Not forgetting %ebp if needed. */
530ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (passBBP) {
531ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(argreg == 1);
532ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, mk_iMOVsd_RR( hregX86_EBP(), argregs[0]));
533ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         not_done_yet--;
534ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
535ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
536ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* ------ END deal with regparms ------ */
537ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
538ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
539ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
540ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* No regparms.  Heave %ebp on the stack if needed. */
541ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (passBBP) {
542ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, X86Instr_Push(X86RMI_Reg(hregX86_EBP())));
543ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         n_arg_ws++;
544ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         not_done_yet--;
545ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
546ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
547ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
548ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
549ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(not_done_yet == 0);
550ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
551ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* ------ END marshall all arguments ------ */
552ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
553ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Now we can compute the condition.  We can't do it earlier
554ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      because the argument computations could trash the condition
555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      codes.  Be a bit clever to handle the common case where the
556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      guard is 1:Bit. */
557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   cc = Xcc_ALWAYS;
558ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (guard) {
559ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (guard->tag == Iex_Const
560ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          && guard->Iex.Const.con->tag == Ico_U1
561ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          && guard->Iex.Const.con->Ico.U1 == True) {
562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* unconditional -- do nothing */
563ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else {
564ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         cc = iselCondCode( env, guard );
565ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
566ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
567ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
568ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* call the helper, and get the args off the stack afterwards. */
569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   callHelperAndClearArgs( env, cc, cee, n_arg_ws );
570ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
571ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
572ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
573ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Given a guest-state array descriptor, an index expression and a
574ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   bias, generate an X86AMode holding the relevant guest state
575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   offset. */
576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownX86AMode* genGuestArrayOffset ( ISelEnv* env, IRRegArray* descr,
579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                IRExpr* off, Int bias )
580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
581ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   HReg tmp, roff;
582ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int  elemSz = sizeofIRType(descr->elemTy);
583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int  nElems = descr->nElems;
584ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int  shift  = 0;
585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
586ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* throw out any cases not generated by an x86 front end.  In
587ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      theory there might be a day where we need to handle them -- if
588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      we ever run non-x86-guest on x86 host. */
589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (nElems != 8)
591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vpanic("genGuestArrayOffset(x86 host)(1)");
592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (elemSz) {
594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 1:  shift = 0; break;
595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 4:  shift = 2; break;
596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 8:  shift = 3; break;
597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default: vpanic("genGuestArrayOffset(x86 host)(2)");
598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Compute off into a reg, %off.  Then return:
601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
602ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         movl %off, %tmp
603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addl $bias, %tmp  (if bias != 0)
604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         andl %tmp, 7
605ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ... base(%ebp, %tmp, shift) ...
606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   */
607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tmp  = newVRegI(env);
608ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   roff = iselIntExpr_R(env, off);
609ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   addInstr(env, mk_iMOVsd_RR(roff, tmp));
610ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (bias != 0) {
611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env,
612ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               X86Instr_Alu32R(Xalu_ADD, X86RMI_Imm(bias), tmp));
613ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
614ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   addInstr(env,
615ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            X86Instr_Alu32R(Xalu_AND, X86RMI_Imm(7), tmp));
616ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return
617ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      X86AMode_IRRS( descr->base, hregX86_EBP(), tmp, shift );
618ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
619ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
620ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
621ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Mess with the FPU's rounding mode: set to the default rounding mode
622ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   (DEFAULT_FPUCW). */
623ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
624ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid set_FPU_rounding_default ( ISelEnv* env )
625ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
626ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* pushl $DEFAULT_FPUCW
627ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      fldcw 0(%esp)
628ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addl $4, %esp
629ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   */
630ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   X86AMode* zero_esp = X86AMode_IR(0, hregX86_ESP());
631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   addInstr(env, X86Instr_Push(X86RMI_Imm(DEFAULT_FPUCW)));
632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   addInstr(env, X86Instr_FpLdCW(zero_esp));
633ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   add_to_esp(env, 4);
634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Mess with the FPU's rounding mode: 'mode' is an I32-typed
638ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   expression denoting a value in the range 0 .. 3, indicating a round
639ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   mode encoded as per type IRRoundingMode.  Set the x87 FPU to have
640ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   the same rounding.
641ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
642ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
643ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid set_FPU_rounding_mode ( ISelEnv* env, IRExpr* mode )
644ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
645ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   HReg rrm  = iselIntExpr_R(env, mode);
646ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   HReg rrm2 = newVRegI(env);
647ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   X86AMode* zero_esp = X86AMode_IR(0, hregX86_ESP());
648ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
649ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* movl  %rrm, %rrm2
650ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      andl  $3, %rrm2   -- shouldn't be needed; paranoia
651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      shll  $10, %rrm2
652ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      orl   $DEFAULT_FPUCW, %rrm2
653ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      pushl %rrm2
654ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      fldcw 0(%esp)
655ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addl  $4, %esp
656ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   */
657ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   addInstr(env, mk_iMOVsd_RR(rrm, rrm2));
658ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   addInstr(env, X86Instr_Alu32R(Xalu_AND, X86RMI_Imm(3), rrm2));
659ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   addInstr(env, X86Instr_Sh32(Xsh_SHL, 10, rrm2));
660ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   addInstr(env, X86Instr_Alu32R(Xalu_OR, X86RMI_Imm(DEFAULT_FPUCW), rrm2));
661ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   addInstr(env, X86Instr_Push(X86RMI_Reg(rrm2)));
662ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   addInstr(env, X86Instr_FpLdCW(zero_esp));
663ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   add_to_esp(env, 4);
664ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
665ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
666ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
667ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Generate !src into a new vector register, and be sure that the code
668ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   is SSE1 compatible.  Amazing that Intel doesn't offer a less crappy
669ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   way to do this.
670ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
671ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic HReg do_sse_Not128 ( ISelEnv* env, HReg src )
672ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
673ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   HReg dst = newVRegV(env);
674ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Set dst to zero.  If dst contains a NaN then all hell might
675ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break loose after the comparison.  So, first zero it. */
676ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   addInstr(env, X86Instr_SseReRg(Xsse_XOR, dst, dst));
677ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* And now make it all 1s ... */
678ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   addInstr(env, X86Instr_Sse32Fx4(Xsse_CMPEQF, dst, dst));
679ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Finally, xor 'src' into it. */
680ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   addInstr(env, X86Instr_SseReRg(Xsse_XOR, src, dst));
681ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Doesn't that just totally suck? */
682ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return dst;
683ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
684ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
685ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
686ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Round an x87 FPU value to 53-bit-mantissa precision, to be used
687ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   after most non-simple FPU operations (simple = +, -, *, / and
688ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   sqrt).
689ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
690ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   This could be done a lot more efficiently if needed, by loading
691ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   zero and adding it to the value to be rounded (fldz ; faddp?).
692ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
693ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void roundToF64 ( ISelEnv* env, HReg reg )
694ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
695ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   X86AMode* zero_esp = X86AMode_IR(0, hregX86_ESP());
696ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   sub_from_esp(env, 8);
697ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   addInstr(env, X86Instr_FpLdSt(False/*store*/, 8, reg, zero_esp));
698ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   addInstr(env, X86Instr_FpLdSt(True/*load*/, 8, reg, zero_esp));
699ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   add_to_esp(env, 8);
700ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
701ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
702ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
703ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------*/
704ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- ISEL: Integer expressions (32/16/8 bit)           ---*/
705ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------*/
706ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
707ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Select insns for an integer-typed expression, and add them to the
708ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   code list.  Return a reg holding the result.  This reg will be a
709ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   virtual register.  THE RETURNED REG MUST NOT BE MODIFIED.  If you
710ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   want to modify it, ask for a new vreg, copy it in there, and modify
711ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   the copy.  The register allocator will do its best to map both
712ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vregs to the same real register, so the copies will often disappear
713ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   later in the game.
714ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
715ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   This should handle expressions of 32, 16 and 8-bit type.  All
716ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   results are returned in a 32-bit register.  For 16- and 8-bit
717ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   expressions, the upper 16/24 bits are arbitrary, so you should mask
718ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   or sign extend partial values if necessary.
719ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
720ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
721ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic HReg iselIntExpr_R ( ISelEnv* env, IRExpr* e )
722ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
723ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   HReg r = iselIntExpr_R_wrk(env, e);
724ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* sanity checks ... */
725ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  if 0
726ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vex_printf("\n"); ppIRExpr(e); vex_printf("\n");
727ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  endif
728ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(hregClass(r) == HRcInt32);
729ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(hregIsVirtual(r));
730ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return r;
731ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
732ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
733ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* DO NOT CALL THIS DIRECTLY ! */
734ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic HReg iselIntExpr_R_wrk ( ISelEnv* env, IRExpr* e )
735ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
736ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   MatchInfo mi;
737ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
738ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRType ty = typeOfIRExpr(env->type_env,e);
739ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(ty == Ity_I32 || ty == Ity_I16 || ty == Ity_I8);
740ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
741ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (e->tag) {
742ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
743ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* --------- TEMP --------- */
744ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Iex_RdTmp: {
745ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return lookupIRTemp(env, e->Iex.RdTmp.tmp);
746ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
747ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
748ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* --------- LOAD --------- */
749ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Iex_Load: {
750ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HReg dst = newVRegI(env);
751ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      X86AMode* amode = iselIntExpr_AMode ( env, e->Iex.Load.addr );
752ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
753ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* We can't handle big-endian loads, nor load-linked. */
754ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (e->Iex.Load.end != Iend_LE)
755ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto irreducible;
756ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
757ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (ty == Ity_I32) {
758ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, X86Instr_Alu32R(Xalu_MOV,
759ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                       X86RMI_Mem(amode), dst) );
760ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return dst;
761ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
762ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (ty == Ity_I16) {
763ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, X86Instr_LoadEX(2,False,amode,dst));
764ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return dst;
765ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
766ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (ty == Ity_I8) {
767ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, X86Instr_LoadEX(1,False,amode,dst));
768ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return dst;
769ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
770ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
771ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
772ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
773ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* --------- TERNARY OP --------- */
774ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Iex_Triop: {
775ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* C3210 flags following FPU partial remainder (fprem), both
776ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IEEE compliant (PREM1) and non-IEEE compliant (PREM). */
777ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (e->Iex.Triop.op == Iop_PRemC3210F64
778ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          || e->Iex.Triop.op == Iop_PRem1C3210F64) {
779ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg junk = newVRegF(env);
780ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg dst  = newVRegI(env);
781ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg srcL = iselDblExpr(env, e->Iex.Triop.arg2);
782ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg srcR = iselDblExpr(env, e->Iex.Triop.arg3);
783ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* XXXROUNDINGFIXME */
784ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* set roundingmode here */
785ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, X86Instr_FpBinary(
786ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           e->Iex.Binop.op==Iop_PRemC3210F64
787ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              ? Xfp_PREM : Xfp_PREM1,
788ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           srcL,srcR,junk
789ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 ));
790ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* The previous pseudo-insn will have left the FPU's C3210
791ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            flags set correctly.  So bag them. */
792ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, X86Instr_FpStSW_AX());
793ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, mk_iMOVsd_RR(hregX86_EAX(), dst));
794ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, X86Instr_Alu32R(Xalu_AND, X86RMI_Imm(0x4700), dst));
795ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return dst;
796ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
797ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
798ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
799ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
800ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
801ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* --------- BINARY OP --------- */
802ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Iex_Binop: {
803ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      X86AluOp   aluOp;
804ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      X86ShiftOp shOp;
805ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
806ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Pattern: Sub32(0,x) */
807ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (e->Iex.Binop.op == Iop_Sub32 && isZeroU32(e->Iex.Binop.arg1)) {
808ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg dst = newVRegI(env);
809ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg reg = iselIntExpr_R(env, e->Iex.Binop.arg2);
810ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, mk_iMOVsd_RR(reg,dst));
811ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, X86Instr_Unary32(Xun_NEG,dst));
812ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return dst;
813ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
814ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
815ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Is it an addition or logical style op? */
816ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch (e->Iex.Binop.op) {
817ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_Add8: case Iop_Add16: case Iop_Add32:
818ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            aluOp = Xalu_ADD; break;
819ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_Sub8: case Iop_Sub16: case Iop_Sub32:
820ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            aluOp = Xalu_SUB; break;
821ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_And8: case Iop_And16: case Iop_And32:
822ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            aluOp = Xalu_AND; break;
823ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_Or8: case Iop_Or16: case Iop_Or32:
824ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            aluOp = Xalu_OR; break;
825ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_Xor8: case Iop_Xor16: case Iop_Xor32:
826ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            aluOp = Xalu_XOR; break;
827ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_Mul16: case Iop_Mul32:
828ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            aluOp = Xalu_MUL; break;
829ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         default:
830ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            aluOp = Xalu_INVALID; break;
831ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
832ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* For commutative ops we assume any literal
833ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         values are on the second operand. */
834ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (aluOp != Xalu_INVALID) {
835ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg dst    = newVRegI(env);
836ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg reg    = iselIntExpr_R(env, e->Iex.Binop.arg1);
837ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         X86RMI* rmi = iselIntExpr_RMI(env, e->Iex.Binop.arg2);
838ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, mk_iMOVsd_RR(reg,dst));
839ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, X86Instr_Alu32R(aluOp, rmi, dst));
840ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return dst;
841ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
842ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Could do better here; forcing the first arg into a reg
843ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         isn't always clever.
844ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         -- t70 = Xor32(And32(Xor32(LDle:I32(Add32(t41,0xFFFFFFA0:I32)),
845ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        LDle:I32(Add32(t41,0xFFFFFFA4:I32))),LDle:I32(Add32(
846ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        t41,0xFFFFFFA8:I32))),LDle:I32(Add32(t41,0xFFFFFFA0:I32)))
847ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            movl 0xFFFFFFA0(%vr41),%vr107
848ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            movl 0xFFFFFFA4(%vr41),%vr108
849ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            movl %vr107,%vr106
850ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            xorl %vr108,%vr106
851ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            movl 0xFFFFFFA8(%vr41),%vr109
852ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            movl %vr106,%vr105
853ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            andl %vr109,%vr105
854ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            movl 0xFFFFFFA0(%vr41),%vr110
855ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            movl %vr105,%vr104
856ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            xorl %vr110,%vr104
857ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            movl %vr104,%vr70
858ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      */
859ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
860ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Perhaps a shift op? */
861ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch (e->Iex.Binop.op) {
862ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_Shl32: case Iop_Shl16: case Iop_Shl8:
863ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            shOp = Xsh_SHL; break;
864ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_Shr32: case Iop_Shr16: case Iop_Shr8:
865ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            shOp = Xsh_SHR; break;
866ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_Sar32: case Iop_Sar16: case Iop_Sar8:
867ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            shOp = Xsh_SAR; break;
868ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         default:
869ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            shOp = Xsh_INVALID; break;
870ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
871ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (shOp != Xsh_INVALID) {
872ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg dst = newVRegI(env);
873ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
874ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* regL = the value to be shifted */
875ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg regL   = iselIntExpr_R(env, e->Iex.Binop.arg1);
876ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, mk_iMOVsd_RR(regL,dst));
877ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
878ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Do any necessary widening for 16/8 bit operands */
879ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         switch (e->Iex.Binop.op) {
880ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Iop_Shr8:
881ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               addInstr(env, X86Instr_Alu32R(
882ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                Xalu_AND, X86RMI_Imm(0xFF), dst));
883ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
884ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Iop_Shr16:
885ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               addInstr(env, X86Instr_Alu32R(
886ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                Xalu_AND, X86RMI_Imm(0xFFFF), dst));
887ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
888ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Iop_Sar8:
889ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               addInstr(env, X86Instr_Sh32(Xsh_SHL, 24, dst));
890ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               addInstr(env, X86Instr_Sh32(Xsh_SAR, 24, dst));
891ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
892ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Iop_Sar16:
893ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               addInstr(env, X86Instr_Sh32(Xsh_SHL, 16, dst));
894ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               addInstr(env, X86Instr_Sh32(Xsh_SAR, 16, dst));
895ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
896ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            default: break;
897ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
898ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
899ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Now consider the shift amount.  If it's a literal, we
900ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            can do a much better job than the general case. */
901ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (e->Iex.Binop.arg2->tag == Iex_Const) {
902ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* assert that the IR is well-typed */
903ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            Int nshift;
904ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vassert(e->Iex.Binop.arg2->Iex.Const.con->tag == Ico_U8);
905ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            nshift = e->Iex.Binop.arg2->Iex.Const.con->Ico.U8;
906ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    vassert(nshift >= 0);
907ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    if (nshift > 0)
908ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               /* Can't allow nshift==0 since that means %cl */
909ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               addInstr(env, X86Instr_Sh32( shOp, nshift, dst ));
910ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
911ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* General case; we have to force the amount into %cl. */
912ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg regR = iselIntExpr_R(env, e->Iex.Binop.arg2);
913ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, mk_iMOVsd_RR(regR,hregX86_ECX()));
914ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, X86Instr_Sh32(shOp, 0/* %cl */, dst));
915ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
916ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return dst;
917ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
918ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
919ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Handle misc other ops. */
920ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
921ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (e->Iex.Binop.op == Iop_Max32U) {
922ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg src1 = iselIntExpr_R(env, e->Iex.Binop.arg1);
923ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg dst  = newVRegI(env);
924ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg src2 = iselIntExpr_R(env, e->Iex.Binop.arg2);
925ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, mk_iMOVsd_RR(src1,dst));
926ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, X86Instr_Alu32R(Xalu_CMP, X86RMI_Reg(src2), dst));
927ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, X86Instr_CMov32(Xcc_B, X86RM_Reg(src2), dst));
928ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return dst;
929ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
930ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
931ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (e->Iex.Binop.op == Iop_8HLto16) {
932ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg hi8  = newVRegI(env);
933ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg lo8  = newVRegI(env);
934ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg hi8s = iselIntExpr_R(env, e->Iex.Binop.arg1);
935ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg lo8s = iselIntExpr_R(env, e->Iex.Binop.arg2);
936ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, mk_iMOVsd_RR(hi8s, hi8));
937ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, mk_iMOVsd_RR(lo8s, lo8));
938ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, X86Instr_Sh32(Xsh_SHL, 8, hi8));
939ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, X86Instr_Alu32R(Xalu_AND, X86RMI_Imm(0xFF), lo8));
940ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, X86Instr_Alu32R(Xalu_OR, X86RMI_Reg(lo8), hi8));
941ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return hi8;
942ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
943ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
944ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (e->Iex.Binop.op == Iop_16HLto32) {
945ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg hi16  = newVRegI(env);
946ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg lo16  = newVRegI(env);
947ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg hi16s = iselIntExpr_R(env, e->Iex.Binop.arg1);
948ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg lo16s = iselIntExpr_R(env, e->Iex.Binop.arg2);
949ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, mk_iMOVsd_RR(hi16s, hi16));
950ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, mk_iMOVsd_RR(lo16s, lo16));
951ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, X86Instr_Sh32(Xsh_SHL, 16, hi16));
952ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, X86Instr_Alu32R(Xalu_AND, X86RMI_Imm(0xFFFF), lo16));
953ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, X86Instr_Alu32R(Xalu_OR, X86RMI_Reg(lo16), hi16));
954ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return hi16;
955ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
956ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
957ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (e->Iex.Binop.op == Iop_MullS16 || e->Iex.Binop.op == Iop_MullS8
958ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          || e->Iex.Binop.op == Iop_MullU16 || e->Iex.Binop.op == Iop_MullU8) {
959ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg a16   = newVRegI(env);
960ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg b16   = newVRegI(env);
961ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg a16s  = iselIntExpr_R(env, e->Iex.Binop.arg1);
962ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg b16s  = iselIntExpr_R(env, e->Iex.Binop.arg2);
963ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         Int  shift = (e->Iex.Binop.op == Iop_MullS8
964ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       || e->Iex.Binop.op == Iop_MullU8)
965ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         ? 24 : 16;
966ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         X86ShiftOp shr_op = (e->Iex.Binop.op == Iop_MullS8
967ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              || e->Iex.Binop.op == Iop_MullS16)
968ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                ? Xsh_SAR : Xsh_SHR;
969ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
970ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, mk_iMOVsd_RR(a16s, a16));
971ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, mk_iMOVsd_RR(b16s, b16));
972ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, X86Instr_Sh32(Xsh_SHL, shift, a16));
973ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, X86Instr_Sh32(Xsh_SHL, shift, b16));
974ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, X86Instr_Sh32(shr_op,  shift, a16));
975ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, X86Instr_Sh32(shr_op,  shift, b16));
976ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, X86Instr_Alu32R(Xalu_MUL, X86RMI_Reg(a16), b16));
977ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return b16;
978ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
979ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
980ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (e->Iex.Binop.op == Iop_CmpF64) {
981ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg fL = iselDblExpr(env, e->Iex.Binop.arg1);
982ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg fR = iselDblExpr(env, e->Iex.Binop.arg2);
983ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg dst = newVRegI(env);
984ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, X86Instr_FpCmp(fL,fR,dst));
985ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* shift this right 8 bits so as to conform to CmpF64
986ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            definition. */
987ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, X86Instr_Sh32(Xsh_SHR, 8, dst));
988ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return dst;
989ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
990ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
991ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (e->Iex.Binop.op == Iop_F64toI32S
992ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          || e->Iex.Binop.op == Iop_F64toI16S) {
993ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         Int  sz  = e->Iex.Binop.op == Iop_F64toI16S ? 2 : 4;
994ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg rf  = iselDblExpr(env, e->Iex.Binop.arg2);
995ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg dst = newVRegI(env);
996ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
997ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Used several times ... */
998ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         X86AMode* zero_esp = X86AMode_IR(0, hregX86_ESP());
999ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1000ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 /* rf now holds the value to be converted, and rrm holds the
1001ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    rounding mode value, encoded as per the IRRoundingMode
1002ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    enum.  The first thing to do is set the FPU's rounding
1003ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    mode accordingly. */
1004ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1005ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Create a space for the format conversion. */
1006ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* subl $4, %esp */
1007ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         sub_from_esp(env, 4);
1008ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1009ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 /* Set host rounding mode */
1010ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 set_FPU_rounding_mode( env, e->Iex.Binop.arg1 );
1011ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1012ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* gistw/l %rf, 0(%esp) */
1013ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, X86Instr_FpLdStI(False/*store*/,
1014ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                        toUChar(sz), rf, zero_esp));
1015ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1016ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (sz == 2) {
1017ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* movzwl 0(%esp), %dst */
1018ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, X86Instr_LoadEX(2,False,zero_esp,dst));
1019ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
1020ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* movl 0(%esp), %dst */
1021ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vassert(sz == 4);
1022ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, X86Instr_Alu32R(
1023ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             Xalu_MOV, X86RMI_Mem(zero_esp), dst));
1024ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
1025ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1026ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 /* Restore default FPU rounding. */
1027ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         set_FPU_rounding_default( env );
1028ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1029ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* addl $4, %esp */
1030ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 add_to_esp(env, 4);
1031ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return dst;
1032ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1033ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1034ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
1035ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1036ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1037ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* --------- UNARY OP --------- */
1038ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Iex_Unop: {
1039ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1040ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* 1Uto8(32to1(expr32)) */
1041ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (e->Iex.Unop.op == Iop_1Uto8) {
1042ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DECLARE_PATTERN(p_32to1_then_1Uto8);
1043ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DEFINE_PATTERN(p_32to1_then_1Uto8,
1044ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        unop(Iop_1Uto8,unop(Iop_32to1,bind(0))));
1045ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (matchIRExpr(&mi,p_32to1_then_1Uto8,e)) {
1046ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            IRExpr* expr32 = mi.bindee[0];
1047ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg dst = newVRegI(env);
1048ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg src = iselIntExpr_R(env, expr32);
1049ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, mk_iMOVsd_RR(src,dst) );
1050ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, X86Instr_Alu32R(Xalu_AND,
1051ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                          X86RMI_Imm(1), dst));
1052ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return dst;
1053ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
1054ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1055ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1056ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* 8Uto32(LDle(expr32)) */
1057ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (e->Iex.Unop.op == Iop_8Uto32) {
1058ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DECLARE_PATTERN(p_LDle8_then_8Uto32);
1059ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DEFINE_PATTERN(p_LDle8_then_8Uto32,
1060ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        unop(Iop_8Uto32,
1061ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             IRExpr_Load(Iend_LE,Ity_I8,bind(0))) );
1062ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (matchIRExpr(&mi,p_LDle8_then_8Uto32,e)) {
1063ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg dst = newVRegI(env);
1064ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            X86AMode* amode = iselIntExpr_AMode ( env, mi.bindee[0] );
1065ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, X86Instr_LoadEX(1,False,amode,dst));
1066ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return dst;
1067ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
1068ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1069ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1070ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* 8Sto32(LDle(expr32)) */
1071ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (e->Iex.Unop.op == Iop_8Sto32) {
1072ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DECLARE_PATTERN(p_LDle8_then_8Sto32);
1073ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DEFINE_PATTERN(p_LDle8_then_8Sto32,
1074ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        unop(Iop_8Sto32,
1075ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             IRExpr_Load(Iend_LE,Ity_I8,bind(0))) );
1076ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (matchIRExpr(&mi,p_LDle8_then_8Sto32,e)) {
1077ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg dst = newVRegI(env);
1078ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            X86AMode* amode = iselIntExpr_AMode ( env, mi.bindee[0] );
1079ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, X86Instr_LoadEX(1,True,amode,dst));
1080ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return dst;
1081ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
1082ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1083ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1084ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* 16Uto32(LDle(expr32)) */
1085ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (e->Iex.Unop.op == Iop_16Uto32) {
1086ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DECLARE_PATTERN(p_LDle16_then_16Uto32);
1087ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DEFINE_PATTERN(p_LDle16_then_16Uto32,
1088ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        unop(Iop_16Uto32,
1089ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             IRExpr_Load(Iend_LE,Ity_I16,bind(0))) );
1090ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (matchIRExpr(&mi,p_LDle16_then_16Uto32,e)) {
1091ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg dst = newVRegI(env);
1092ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            X86AMode* amode = iselIntExpr_AMode ( env, mi.bindee[0] );
1093ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, X86Instr_LoadEX(2,False,amode,dst));
1094ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return dst;
1095ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
1096ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1097ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1098ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* 8Uto32(GET:I8) */
1099ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (e->Iex.Unop.op == Iop_8Uto32) {
1100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (e->Iex.Unop.arg->tag == Iex_Get) {
1101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg      dst;
1102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            X86AMode* amode;
1103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vassert(e->Iex.Unop.arg->Iex.Get.ty == Ity_I8);
1104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            dst = newVRegI(env);
1105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            amode = X86AMode_IR(e->Iex.Unop.arg->Iex.Get.offset,
1106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                hregX86_EBP());
1107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, X86Instr_LoadEX(1,False,amode,dst));
1108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return dst;
1109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
1110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* 16to32(GET:I16) */
1113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (e->Iex.Unop.op == Iop_16Uto32) {
1114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (e->Iex.Unop.arg->tag == Iex_Get) {
1115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg      dst;
1116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            X86AMode* amode;
1117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vassert(e->Iex.Unop.arg->Iex.Get.ty == Ity_I16);
1118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            dst = newVRegI(env);
1119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            amode = X86AMode_IR(e->Iex.Unop.arg->Iex.Get.offset,
1120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                hregX86_EBP());
1121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, X86Instr_LoadEX(2,False,amode,dst));
1122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return dst;
1123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
1124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch (e->Iex.Unop.op) {
1127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_8Uto16:
1128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_8Uto32:
1129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_16Uto32: {
1130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg dst = newVRegI(env);
1131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg src = iselIntExpr_R(env, e->Iex.Unop.arg);
1132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            UInt mask = e->Iex.Unop.op==Iop_16Uto32 ? 0xFFFF : 0xFF;
1133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, mk_iMOVsd_RR(src,dst) );
1134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, X86Instr_Alu32R(Xalu_AND,
1135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                          X86RMI_Imm(mask), dst));
1136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return dst;
1137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
1138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_8Sto16:
1139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_8Sto32:
1140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_16Sto32: {
1141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg dst = newVRegI(env);
1142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg src = iselIntExpr_R(env, e->Iex.Unop.arg);
1143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            UInt amt = e->Iex.Unop.op==Iop_16Sto32 ? 16 : 24;
1144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, mk_iMOVsd_RR(src,dst) );
1145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, X86Instr_Sh32(Xsh_SHL, amt, dst));
1146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, X86Instr_Sh32(Xsh_SAR, amt, dst));
1147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return dst;
1148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
1149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 case Iop_Not8:
1150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 case Iop_Not16:
1151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_Not32: {
1152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg dst = newVRegI(env);
1153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg src = iselIntExpr_R(env, e->Iex.Unop.arg);
1154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, mk_iMOVsd_RR(src,dst) );
1155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, X86Instr_Unary32(Xun_NOT,dst));
1156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return dst;
1157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
1158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_64HIto32: {
1159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg rHi, rLo;
1160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            iselInt64Expr(&rHi,&rLo, env, e->Iex.Unop.arg);
1161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return rHi; /* and abandon rLo .. poor wee thing :-) */
1162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
1163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_64to32: {
1164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg rHi, rLo;
1165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            iselInt64Expr(&rHi,&rLo, env, e->Iex.Unop.arg);
1166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return rLo; /* similar stupid comment to the above ... */
1167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
1168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_16HIto8:
1169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_32HIto16: {
1170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg dst  = newVRegI(env);
1171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg src  = iselIntExpr_R(env, e->Iex.Unop.arg);
1172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            Int shift = e->Iex.Unop.op == Iop_16HIto8 ? 8 : 16;
1173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, mk_iMOVsd_RR(src,dst) );
1174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, X86Instr_Sh32(Xsh_SHR, shift, dst));
1175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return dst;
1176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
1177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_1Uto32:
1178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_1Uto8: {
1179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg dst         = newVRegI(env);
1180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            X86CondCode cond = iselCondCode(env, e->Iex.Unop.arg);
1181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, X86Instr_Set32(cond,dst));
1182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return dst;
1183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
1184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_1Sto8:
1185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_1Sto16:
1186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_1Sto32: {
1187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* could do better than this, but for now ... */
1188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg dst         = newVRegI(env);
1189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            X86CondCode cond = iselCondCode(env, e->Iex.Unop.arg);
1190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, X86Instr_Set32(cond,dst));
1191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, X86Instr_Sh32(Xsh_SHL, 31, dst));
1192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, X86Instr_Sh32(Xsh_SAR, 31, dst));
1193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return dst;
1194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
1195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_Ctz32: {
1196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* Count trailing zeroes, implemented by x86 'bsfl' */
1197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg dst = newVRegI(env);
1198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg src = iselIntExpr_R(env, e->Iex.Unop.arg);
1199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, X86Instr_Bsfr32(True,src,dst));
1200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return dst;
1201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
1202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_Clz32: {
1203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* Count leading zeroes.  Do 'bsrl' to establish the index
1204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               of the highest set bit, and subtract that value from
1205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               31. */
1206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg tmp = newVRegI(env);
1207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg dst = newVRegI(env);
1208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg src = iselIntExpr_R(env, e->Iex.Unop.arg);
1209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, X86Instr_Bsfr32(False,src,tmp));
1210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, X86Instr_Alu32R(Xalu_MOV,
1211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                          X86RMI_Imm(31), dst));
1212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, X86Instr_Alu32R(Xalu_SUB,
1213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                          X86RMI_Reg(tmp), dst));
1214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return dst;
1215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
1216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_CmpwNEZ32: {
1218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg dst = newVRegI(env);
1219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg src = iselIntExpr_R(env, e->Iex.Unop.arg);
1220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, mk_iMOVsd_RR(src,dst));
1221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, X86Instr_Unary32(Xun_NEG,dst));
1222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, X86Instr_Alu32R(Xalu_OR,
1223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                          X86RMI_Reg(src), dst));
1224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, X86Instr_Sh32(Xsh_SAR, 31, dst));
1225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return dst;
1226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
1227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_Left8:
1228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_Left16:
1229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_Left32: {
1230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg dst = newVRegI(env);
1231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg src = iselIntExpr_R(env, e->Iex.Unop.arg);
1232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, mk_iMOVsd_RR(src, dst));
1233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, X86Instr_Unary32(Xun_NEG, dst));
1234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, X86Instr_Alu32R(Xalu_OR, X86RMI_Reg(src), dst));
1235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return dst;
1236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
1237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_V128to32: {
1239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg      dst  = newVRegI(env);
1240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg      vec  = iselVecExpr(env, e->Iex.Unop.arg);
1241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            X86AMode* esp0 = X86AMode_IR(0, hregX86_ESP());
1242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            sub_from_esp(env, 16);
1243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, X86Instr_SseLdSt(False/*store*/, vec, esp0));
1244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, X86Instr_Alu32R( Xalu_MOV, X86RMI_Mem(esp0), dst ));
1245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            add_to_esp(env, 16);
1246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return dst;
1247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
1248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* ReinterpF32asI32(e) */
1250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Given an IEEE754 single, produce an I32 with the same bit
1251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            pattern.  Keep stack 8-aligned even though only using 4
1252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            bytes. */
1253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_ReinterpF32asI32: {
1254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg rf   = iselFltExpr(env, e->Iex.Unop.arg);
1255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg dst  = newVRegI(env);
1256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            X86AMode* zero_esp = X86AMode_IR(0, hregX86_ESP());
1257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* paranoia */
1258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            set_FPU_rounding_default(env);
1259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* subl $8, %esp */
1260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            sub_from_esp(env, 8);
1261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* gstF %rf, 0(%esp) */
1262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env,
1263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     X86Instr_FpLdSt(False/*store*/, 4, rf, zero_esp));
1264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* movl 0(%esp), %dst */
1265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env,
1266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     X86Instr_Alu32R(Xalu_MOV, X86RMI_Mem(zero_esp), dst));
1267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* addl $8, %esp */
1268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            add_to_esp(env, 8);
1269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return dst;
1270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
1271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_16to8:
1273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_32to8:
1274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_32to16:
1275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* These are no-ops. */
1276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return iselIntExpr_R(env, e->Iex.Unop.arg);
1277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         default:
1279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
1280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
1282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* --------- GET --------- */
1285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Iex_Get: {
1286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (ty == Ity_I32) {
1287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg dst = newVRegI(env);
1288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, X86Instr_Alu32R(
1289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          Xalu_MOV,
1290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          X86RMI_Mem(X86AMode_IR(e->Iex.Get.offset,
1291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                                 hregX86_EBP())),
1292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          dst));
1293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return dst;
1294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (ty == Ity_I8 || ty == Ity_I16) {
1296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg dst = newVRegI(env);
1297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, X86Instr_LoadEX(
1298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          toUChar(ty==Ity_I8 ? 1 : 2),
1299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          False,
1300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          X86AMode_IR(e->Iex.Get.offset,hregX86_EBP()),
1301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          dst));
1302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return dst;
1303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
1305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Iex_GetI: {
1308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      X86AMode* am
1309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         = genGuestArrayOffset(
1310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              env, e->Iex.GetI.descr,
1311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   e->Iex.GetI.ix, e->Iex.GetI.bias );
1312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HReg dst = newVRegI(env);
1313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (ty == Ity_I8) {
1314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, X86Instr_LoadEX( 1, False, am, dst ));
1315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return dst;
1316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (ty == Ity_I32) {
1318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, X86Instr_Alu32R(Xalu_MOV, X86RMI_Mem(am), dst));
1319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return dst;
1320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
1322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* --------- CCALL --------- */
1325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Iex_CCall: {
1326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HReg    dst = newVRegI(env);
1327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert(ty == e->Iex.CCall.retty);
1328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* be very restrictive for now.  Only 32/64-bit ints allowed
1330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         for args, and 32 bits for return type. */
1331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (e->Iex.CCall.retty != Ity_I32)
1332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto irreducible;
1333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Marshal args, do the call, clear stack. */
1335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      doHelperCall( env, False, NULL, e->Iex.CCall.cee, e->Iex.CCall.args );
1336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env, mk_iMOVsd_RR(hregX86_EAX(), dst));
1338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return dst;
1339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* --------- LITERAL --------- */
1342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* 32/16/8-bit literals */
1343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Iex_Const: {
1344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      X86RMI* rmi = iselIntExpr_RMI ( env, e );
1345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HReg    r   = newVRegI(env);
1346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env, X86Instr_Alu32R(Xalu_MOV, rmi, r));
1347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return r;
1348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* --------- MULTIPLEX --------- */
1351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Iex_Mux0X: {
1352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     if ((ty == Ity_I32 || ty == Ity_I16 || ty == Ity_I8)
1353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         && typeOfIRExpr(env->type_env,e->Iex.Mux0X.cond) == Ity_I8) {
1354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        X86RM* r8;
1355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        HReg   rX  = iselIntExpr_R(env, e->Iex.Mux0X.exprX);
1356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        X86RM* r0  = iselIntExpr_RM(env, e->Iex.Mux0X.expr0);
1357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        HReg   dst = newVRegI(env);
1358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        addInstr(env, mk_iMOVsd_RR(rX,dst));
1359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        r8 = iselIntExpr_RM(env, e->Iex.Mux0X.cond);
1360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        addInstr(env, X86Instr_Test32(0xFF, r8));
1361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        addInstr(env, X86Instr_CMov32(Xcc_Z,r0,dst));
1362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        return dst;
1363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
1365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   default:
1368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   break;
1369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } /* switch (e->tag) */
1370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* We get here if no pattern matched. */
1372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  irreducible:
1373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ppIRExpr(e);
1374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vpanic("iselIntExpr_R: cannot reduce tree");
1375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------*/
1379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- ISEL: Integer expression auxiliaries              ---*/
1380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------*/
1381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* --------------------- AMODEs --------------------- */
1383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Return an AMode which computes the value of the specified
1385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   expression, possibly also adding insns to the code list as a
1386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   result.  The expression may only be a 32-bit one.
1387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
1388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool sane_AMode ( X86AMode* am )
1390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (am->tag) {
1392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xam_IR:
1393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return
1394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            toBool( hregClass(am->Xam.IR.reg) == HRcInt32
1395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    && (hregIsVirtual(am->Xam.IR.reg)
1396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        || am->Xam.IR.reg == hregX86_EBP()) );
1397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xam_IRRS:
1398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return
1399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            toBool( hregClass(am->Xam.IRRS.base) == HRcInt32
1400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    && hregIsVirtual(am->Xam.IRRS.base)
1401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    && hregClass(am->Xam.IRRS.index) == HRcInt32
1402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    && hregIsVirtual(am->Xam.IRRS.index) );
1403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
1404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        vpanic("sane_AMode: unknown x86 amode tag");
1405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic X86AMode* iselIntExpr_AMode ( ISelEnv* env, IRExpr* e )
1409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   X86AMode* am = iselIntExpr_AMode_wrk(env, e);
1411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(sane_AMode(am));
1412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return am;
1413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* DO NOT CALL THIS DIRECTLY ! */
1416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic X86AMode* iselIntExpr_AMode_wrk ( ISelEnv* env, IRExpr* e )
1417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRType ty = typeOfIRExpr(env->type_env,e);
1419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(ty == Ity_I32);
1420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Add32( Add32(expr1, Shl32(expr2, simm)), imm32 ) */
1422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_Binop
1423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && e->Iex.Binop.op == Iop_Add32
1424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && e->Iex.Binop.arg2->tag == Iex_Const
1425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && e->Iex.Binop.arg2->Iex.Const.con->tag == Ico_U32
1426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && e->Iex.Binop.arg1->tag == Iex_Binop
1427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && e->Iex.Binop.arg1->Iex.Binop.op == Iop_Add32
1428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && e->Iex.Binop.arg1->Iex.Binop.arg2->tag == Iex_Binop
1429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && e->Iex.Binop.arg1->Iex.Binop.arg2->Iex.Binop.op == Iop_Shl32
1430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && e->Iex.Binop.arg1
1431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           ->Iex.Binop.arg2->Iex.Binop.arg2->tag == Iex_Const
1432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && e->Iex.Binop.arg1
1433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           ->Iex.Binop.arg2->Iex.Binop.arg2->Iex.Const.con->tag == Ico_U8) {
1434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt shift = e->Iex.Binop.arg1
1435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    ->Iex.Binop.arg2->Iex.Binop.arg2->Iex.Const.con->Ico.U8;
1436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt imm32 = e->Iex.Binop.arg2->Iex.Const.con->Ico.U32;
1437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (shift == 1 || shift == 2 || shift == 3) {
1438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg r1 = iselIntExpr_R(env, e->Iex.Binop.arg1->Iex.Binop.arg1);
1439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg r2 = iselIntExpr_R(env, e->Iex.Binop.arg1
1440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                       ->Iex.Binop.arg2->Iex.Binop.arg1 );
1441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return X86AMode_IRRS(imm32, r1, r2, shift);
1442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Add32(expr1, Shl32(expr2, imm)) */
1446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_Binop
1447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && e->Iex.Binop.op == Iop_Add32
1448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && e->Iex.Binop.arg2->tag == Iex_Binop
1449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && e->Iex.Binop.arg2->Iex.Binop.op == Iop_Shl32
1450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && e->Iex.Binop.arg2->Iex.Binop.arg2->tag == Iex_Const
1451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && e->Iex.Binop.arg2->Iex.Binop.arg2->Iex.Const.con->tag == Ico_U8) {
1452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt shift = e->Iex.Binop.arg2->Iex.Binop.arg2->Iex.Const.con->Ico.U8;
1453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (shift == 1 || shift == 2 || shift == 3) {
1454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg r1 = iselIntExpr_R(env, e->Iex.Binop.arg1);
1455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg r2 = iselIntExpr_R(env, e->Iex.Binop.arg2->Iex.Binop.arg1 );
1456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return X86AMode_IRRS(0, r1, r2, shift);
1457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Add32(expr,i) */
1461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_Binop
1462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && e->Iex.Binop.op == Iop_Add32
1463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && e->Iex.Binop.arg2->tag == Iex_Const
1464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && e->Iex.Binop.arg2->Iex.Const.con->tag == Ico_U32) {
1465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HReg r1 = iselIntExpr_R(env,  e->Iex.Binop.arg1);
1466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return X86AMode_IR(e->Iex.Binop.arg2->Iex.Const.con->Ico.U32, r1);
1467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Doesn't match anything in particular.  Generate it into
1470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      a register and use that. */
1471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   {
1472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HReg r1 = iselIntExpr_R(env, e);
1473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return X86AMode_IR(0, r1);
1474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* --------------------- RMIs --------------------- */
1479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Similarly, calculate an expression into an X86RMI operand.  As with
1481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   iselIntExpr_R, the expression can have type 32, 16 or 8 bits.  */
1482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic X86RMI* iselIntExpr_RMI ( ISelEnv* env, IRExpr* e )
1484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   X86RMI* rmi = iselIntExpr_RMI_wrk(env, e);
1486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* sanity checks ... */
1487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (rmi->tag) {
1488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xrmi_Imm:
1489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return rmi;
1490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xrmi_Reg:
1491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(hregClass(rmi->Xrmi.Reg.reg) == HRcInt32);
1492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(hregIsVirtual(rmi->Xrmi.Reg.reg));
1493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return rmi;
1494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xrmi_Mem:
1495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(sane_AMode(rmi->Xrmi.Mem.am));
1496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return rmi;
1497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
1498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vpanic("iselIntExpr_RMI: unknown x86 RMI tag");
1499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* DO NOT CALL THIS DIRECTLY ! */
1503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic X86RMI* iselIntExpr_RMI_wrk ( ISelEnv* env, IRExpr* e )
1504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRType ty = typeOfIRExpr(env->type_env,e);
1506ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(ty == Ity_I32 || ty == Ity_I16 || ty == Ity_I8);
1507ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1508ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* special case: immediate */
1509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_Const) {
1510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt u;
1511ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch (e->Iex.Const.con->tag) {
1512ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Ico_U32: u = e->Iex.Const.con->Ico.U32; break;
1513ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Ico_U16: u = 0xFFFF & (e->Iex.Const.con->Ico.U16); break;
1514ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Ico_U8:  u = 0xFF   & (e->Iex.Const.con->Ico.U8); break;
1515ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         default: vpanic("iselIntExpr_RMI.Iex_Const(x86h)");
1516ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1517ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return X86RMI_Imm(u);
1518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* special case: 32-bit GET */
1521ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_Get && ty == Ity_I32) {
1522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return X86RMI_Mem(X86AMode_IR(e->Iex.Get.offset,
1523ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                    hregX86_EBP()));
1524ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1525ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1526ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* special case: 32-bit load from memory */
1527ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_Load && ty == Ity_I32
1528ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && e->Iex.Load.end == Iend_LE) {
1529ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      X86AMode* am = iselIntExpr_AMode(env, e->Iex.Load.addr);
1530ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return X86RMI_Mem(am);
1531ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1532ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1533ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* default case: calculate into a register and return that */
1534ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   {
1535ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HReg r = iselIntExpr_R ( env, e );
1536ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return X86RMI_Reg(r);
1537ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1538ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1539ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1540ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1541ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* --------------------- RIs --------------------- */
1542ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1543ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Calculate an expression into an X86RI operand.  As with
1544ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   iselIntExpr_R, the expression can have type 32, 16 or 8 bits. */
1545ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1546ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic X86RI* iselIntExpr_RI ( ISelEnv* env, IRExpr* e )
1547ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1548ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   X86RI* ri = iselIntExpr_RI_wrk(env, e);
1549ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* sanity checks ... */
1550ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (ri->tag) {
1551ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xri_Imm:
1552ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return ri;
1553ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xri_Reg:
1554ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(hregClass(ri->Xri.Reg.reg) == HRcInt32);
1555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(hregIsVirtual(ri->Xri.Reg.reg));
1556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return ri;
1557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
1558ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vpanic("iselIntExpr_RI: unknown x86 RI tag");
1559ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1560ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1561ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* DO NOT CALL THIS DIRECTLY ! */
1563ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic X86RI* iselIntExpr_RI_wrk ( ISelEnv* env, IRExpr* e )
1564ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1565ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRType ty = typeOfIRExpr(env->type_env,e);
1566ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(ty == Ity_I32 || ty == Ity_I16 || ty == Ity_I8);
1567ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1568ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* special case: immediate */
1569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_Const) {
1570ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt u;
1571ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch (e->Iex.Const.con->tag) {
1572ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Ico_U32: u = e->Iex.Const.con->Ico.U32; break;
1573ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Ico_U16: u = 0xFFFF & (e->Iex.Const.con->Ico.U16); break;
1574ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Ico_U8:  u = 0xFF   & (e->Iex.Const.con->Ico.U8); break;
1575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         default: vpanic("iselIntExpr_RMI.Iex_Const(x86h)");
1576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return X86RI_Imm(u);
1578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* default case: calculate into a register and return that */
1581ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   {
1582ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HReg r = iselIntExpr_R ( env, e );
1583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return X86RI_Reg(r);
1584ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1586ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1587ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* --------------------- RMs --------------------- */
1589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Similarly, calculate an expression into an X86RM operand.  As with
1591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   iselIntExpr_R, the expression can have type 32, 16 or 8 bits.  */
1592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic X86RM* iselIntExpr_RM ( ISelEnv* env, IRExpr* e )
1594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   X86RM* rm = iselIntExpr_RM_wrk(env, e);
1596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* sanity checks ... */
1597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (rm->tag) {
1598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xrm_Reg:
1599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(hregClass(rm->Xrm.Reg.reg) == HRcInt32);
1600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(hregIsVirtual(rm->Xrm.Reg.reg));
1601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return rm;
1602ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Xrm_Mem:
1603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(sane_AMode(rm->Xrm.Mem.am));
1604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return rm;
1605ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
1606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vpanic("iselIntExpr_RM: unknown x86 RM tag");
1607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1608ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1609ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1610ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* DO NOT CALL THIS DIRECTLY ! */
1611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic X86RM* iselIntExpr_RM_wrk ( ISelEnv* env, IRExpr* e )
1612ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1613ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRType ty = typeOfIRExpr(env->type_env,e);
1614ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(ty == Ity_I32 || ty == Ity_I16 || ty == Ity_I8);
1615ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1616ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* special case: 32-bit GET */
1617ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_Get && ty == Ity_I32) {
1618ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return X86RM_Mem(X86AMode_IR(e->Iex.Get.offset,
1619ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                   hregX86_EBP()));
1620ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1621ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1622ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* special case: load from memory */
1623ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1624ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* default case: calculate into a register and return that */
1625ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   {
1626ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HReg r = iselIntExpr_R ( env, e );
1627ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return X86RM_Reg(r);
1628ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1629ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1630ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* --------------------- CONDCODE --------------------- */
1633ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Generate code to evaluated a bit-typed expression, returning the
1635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   condition code which would correspond when the expression would
1636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   notionally have returned 1. */
1637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1638ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic X86CondCode iselCondCode ( ISelEnv* env, IRExpr* e )
1639ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1640ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Uh, there's nothing we can sanity check here, unfortunately. */
1641ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return iselCondCode_wrk(env,e);
1642ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1643ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1644ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* DO NOT CALL THIS DIRECTLY ! */
1645ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic X86CondCode iselCondCode_wrk ( ISelEnv* env, IRExpr* e )
1646ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1647ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   MatchInfo mi;
1648ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1649ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(e);
1650ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(typeOfIRExpr(env->type_env,e) == Ity_I1);
1651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1652ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* var */
1653ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_RdTmp) {
1654ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HReg r32 = lookupIRTemp(env, e->Iex.RdTmp.tmp);
1655ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Test32 doesn't modify r32; so this is OK. */
1656ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env, X86Instr_Test32(1,X86RM_Reg(r32)));
1657ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return Xcc_NZ;
1658ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1659ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1660ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Constant 1:Bit */
1661ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_Const) {
1662ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HReg r;
1663ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert(e->Iex.Const.con->tag == Ico_U1);
1664ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert(e->Iex.Const.con->Ico.U1 == True
1665ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              || e->Iex.Const.con->Ico.U1 == False);
1666ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      r = newVRegI(env);
1667ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env, X86Instr_Alu32R(Xalu_MOV,X86RMI_Imm(0),r));
1668ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env, X86Instr_Alu32R(Xalu_XOR,X86RMI_Reg(r),r));
1669ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return e->Iex.Const.con->Ico.U1 ? Xcc_Z : Xcc_NZ;
1670ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1671ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1672ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Not1(e) */
1673ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_Unop && e->Iex.Unop.op == Iop_Not1) {
1674ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Generate code for the arg, and negate the test condition */
1675ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return 1 ^ iselCondCode(env, e->Iex.Unop.arg);
1676ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1677ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1678ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* --- patterns rooted at: 32to1 --- */
1679ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1680ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_Unop
1681ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && e->Iex.Unop.op == Iop_32to1) {
1682ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      X86RM* rm = iselIntExpr_RM(env, e->Iex.Unop.arg);
1683ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env, X86Instr_Test32(1,rm));
1684ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return Xcc_NZ;
1685ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1686ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1687ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* --- patterns rooted at: CmpNEZ8 --- */
1688ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1689ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* CmpNEZ8(x) */
1690ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_Unop
1691ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && e->Iex.Unop.op == Iop_CmpNEZ8) {
1692ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      X86RM* rm = iselIntExpr_RM(env, e->Iex.Unop.arg);
1693ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env, X86Instr_Test32(0xFF,rm));
1694ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return Xcc_NZ;
1695ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1696ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1697ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* --- patterns rooted at: CmpNEZ16 --- */
1698ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1699ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* CmpNEZ16(x) */
1700ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_Unop
1701ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && e->Iex.Unop.op == Iop_CmpNEZ16) {
1702ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      X86RM* rm = iselIntExpr_RM(env, e->Iex.Unop.arg);
1703ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env, X86Instr_Test32(0xFFFF,rm));
1704ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return Xcc_NZ;
1705ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1706ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1707ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* --- patterns rooted at: CmpNEZ32 --- */
1708ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1709ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* CmpNEZ32(And32(x,y)) */
1710ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   {
1711ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DECLARE_PATTERN(p_CmpNEZ32_And32);
1712ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DEFINE_PATTERN(p_CmpNEZ32_And32,
1713ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     unop(Iop_CmpNEZ32, binop(Iop_And32, bind(0), bind(1))));
1714ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (matchIRExpr(&mi, p_CmpNEZ32_And32, e)) {
1715ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg    r0   = iselIntExpr_R(env, mi.bindee[0]);
1716ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         X86RMI* rmi1 = iselIntExpr_RMI(env, mi.bindee[1]);
1717ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg    tmp  = newVRegI(env);
1718ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, mk_iMOVsd_RR(r0, tmp));
1719ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, X86Instr_Alu32R(Xalu_AND,rmi1,tmp));
1720ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return Xcc_NZ;
1721ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1722ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1723ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1724ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* CmpNEZ32(Or32(x,y)) */
1725ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   {
1726ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DECLARE_PATTERN(p_CmpNEZ32_Or32);
1727ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DEFINE_PATTERN(p_CmpNEZ32_Or32,
1728ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     unop(Iop_CmpNEZ32, binop(Iop_Or32, bind(0), bind(1))));
1729ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (matchIRExpr(&mi, p_CmpNEZ32_Or32, e)) {
1730ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg    r0   = iselIntExpr_R(env, mi.bindee[0]);
1731ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         X86RMI* rmi1 = iselIntExpr_RMI(env, mi.bindee[1]);
1732ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg    tmp  = newVRegI(env);
1733ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, mk_iMOVsd_RR(r0, tmp));
1734ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, X86Instr_Alu32R(Xalu_OR,rmi1,tmp));
1735ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return Xcc_NZ;
1736ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1737ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1738ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1739ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* CmpNEZ32(GET(..):I32) */
1740ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_Unop
1741ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && e->Iex.Unop.op == Iop_CmpNEZ32
1742ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && e->Iex.Unop.arg->tag == Iex_Get) {
1743ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      X86AMode* am = X86AMode_IR(e->Iex.Unop.arg->Iex.Get.offset,
1744ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                 hregX86_EBP());
1745ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env, X86Instr_Alu32M(Xalu_CMP, X86RI_Imm(0), am));
1746ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return Xcc_NZ;
1747ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1748ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1749ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* CmpNEZ32(x) */
1750ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_Unop
1751ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && e->Iex.Unop.op == Iop_CmpNEZ32) {
1752ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HReg    r1   = iselIntExpr_R(env, e->Iex.Unop.arg);
1753ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      X86RMI* rmi2 = X86RMI_Imm(0);
1754ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env, X86Instr_Alu32R(Xalu_CMP,rmi2,r1));
1755ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return Xcc_NZ;
1756ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1757ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1758ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* --- patterns rooted at: CmpNEZ64 --- */
1759ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1760ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* CmpNEZ64(Or64(x,y)) */
1761ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   {
1762ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DECLARE_PATTERN(p_CmpNEZ64_Or64);
1763ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DEFINE_PATTERN(p_CmpNEZ64_Or64,
1764ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     unop(Iop_CmpNEZ64, binop(Iop_Or64, bind(0), bind(1))));
1765ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (matchIRExpr(&mi, p_CmpNEZ64_Or64, e)) {
1766ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg    hi1, lo1, hi2, lo2;
1767ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg    tmp  = newVRegI(env);
1768ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         iselInt64Expr( &hi1, &lo1, env, mi.bindee[0] );
1769ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, mk_iMOVsd_RR(hi1, tmp));
1770ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, X86Instr_Alu32R(Xalu_OR,X86RMI_Reg(lo1),tmp));
1771ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         iselInt64Expr( &hi2, &lo2, env, mi.bindee[1] );
1772ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, X86Instr_Alu32R(Xalu_OR,X86RMI_Reg(hi2),tmp));
1773ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, X86Instr_Alu32R(Xalu_OR,X86RMI_Reg(lo2),tmp));
1774ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return Xcc_NZ;
1775ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1776ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1777ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1778ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* CmpNEZ64(x) */
1779ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_Unop
1780ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && e->Iex.Unop.op == Iop_CmpNEZ64) {
1781ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HReg hi, lo;
1782ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HReg tmp = newVRegI(env);
1783ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      iselInt64Expr( &hi, &lo, env, e->Iex.Unop.arg );
1784ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env, mk_iMOVsd_RR(hi, tmp));
1785ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env, X86Instr_Alu32R(Xalu_OR,X86RMI_Reg(lo), tmp));
1786ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return Xcc_NZ;
1787ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1788ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1789ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* --- patterns rooted at: Cmp{EQ,NE}{8,16} --- */
1790ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1791ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* CmpEQ8 / CmpNE8 */
1792ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_Binop
1793ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && (e->Iex.Binop.op == Iop_CmpEQ8
1794ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           || e->Iex.Binop.op == Iop_CmpNE8
1795ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           || e->Iex.Binop.op == Iop_CasCmpEQ8
1796ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           || e->Iex.Binop.op == Iop_CasCmpNE8)) {
1797ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (isZeroU8(e->Iex.Binop.arg2)) {
1798ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg    r1   = iselIntExpr_R(env, e->Iex.Binop.arg1);
1799ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, X86Instr_Test32(0xFF,X86RM_Reg(r1)));
1800ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         switch (e->Iex.Binop.op) {
1801ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Iop_CmpEQ8: case Iop_CasCmpEQ8: return Xcc_Z;
1802ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Iop_CmpNE8: case Iop_CasCmpNE8: return Xcc_NZ;
1803ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            default: vpanic("iselCondCode(x86): CmpXX8(expr,0:I8)");
1804ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
1805ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else {
1806ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg    r1   = iselIntExpr_R(env, e->Iex.Binop.arg1);
1807ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         X86RMI* rmi2 = iselIntExpr_RMI(env, e->Iex.Binop.arg2);
1808ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg    r    = newVRegI(env);
1809ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, mk_iMOVsd_RR(r1,r));
1810ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, X86Instr_Alu32R(Xalu_XOR,rmi2,r));
1811ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, X86Instr_Test32(0xFF,X86RM_Reg(r)));
1812ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         switch (e->Iex.Binop.op) {
1813ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Iop_CmpEQ8: case Iop_CasCmpEQ8: return Xcc_Z;
1814ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Iop_CmpNE8: case Iop_CasCmpNE8: return Xcc_NZ;
1815ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            default: vpanic("iselCondCode(x86): CmpXX8(expr,expr)");
1816ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
1817ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1818ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1819ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1820ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* CmpEQ16 / CmpNE16 */
1821ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_Binop
1822ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && (e->Iex.Binop.op == Iop_CmpEQ16
1823ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           || e->Iex.Binop.op == Iop_CmpNE16
1824ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           || e->Iex.Binop.op == Iop_CasCmpEQ16
1825ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           || e->Iex.Binop.op == Iop_CasCmpNE16)) {
1826ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HReg    r1   = iselIntExpr_R(env, e->Iex.Binop.arg1);
1827ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      X86RMI* rmi2 = iselIntExpr_RMI(env, e->Iex.Binop.arg2);
1828ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HReg    r    = newVRegI(env);
1829ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env, mk_iMOVsd_RR(r1,r));
1830ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env, X86Instr_Alu32R(Xalu_XOR,rmi2,r));
1831ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env, X86Instr_Test32(0xFFFF,X86RM_Reg(r)));
1832ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch (e->Iex.Binop.op) {
1833ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_CmpEQ16: case Iop_CasCmpEQ16: return Xcc_Z;
1834ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_CmpNE16: case Iop_CasCmpNE16: return Xcc_NZ;
1835ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         default: vpanic("iselCondCode(x86): CmpXX16");
1836ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1837ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1838ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1839b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   /* CmpNE32(ccall, 32-bit constant) (--smc-check=all optimisation).
1840b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      Saves a "movl %eax, %tmp" compared to the default route. */
1841b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   if (e->tag == Iex_Binop
1842b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov       && e->Iex.Binop.op == Iop_CmpNE32
1843b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov       && e->Iex.Binop.arg1->tag == Iex_CCall
1844b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov       && e->Iex.Binop.arg2->tag == Iex_Const) {
1845b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      IRExpr* cal = e->Iex.Binop.arg1;
1846b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      IRExpr* con = e->Iex.Binop.arg2;
1847b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      /* clone & partial-eval of generic Iex_CCall and Iex_Const cases */
1848b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      vassert(cal->Iex.CCall.retty == Ity_I32); /* else ill-typed IR */
1849b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      vassert(con->Iex.Const.con->tag == Ico_U32);
1850b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      /* Marshal args, do the call. */
1851b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      doHelperCall( env, False, NULL, cal->Iex.CCall.cee, cal->Iex.CCall.args );
1852b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      addInstr(env, X86Instr_Alu32R(Xalu_CMP,
1853b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                    X86RMI_Imm(con->Iex.Const.con->Ico.U32),
1854b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                    hregX86_EAX()));
1855b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      return Xcc_NZ;
1856b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   }
1857b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1858ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Cmp*32*(x,y) */
1859ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_Binop
1860ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && (e->Iex.Binop.op == Iop_CmpEQ32
1861ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           || e->Iex.Binop.op == Iop_CmpNE32
1862ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           || e->Iex.Binop.op == Iop_CmpLT32S
1863ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           || e->Iex.Binop.op == Iop_CmpLT32U
1864ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           || e->Iex.Binop.op == Iop_CmpLE32S
1865ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           || e->Iex.Binop.op == Iop_CmpLE32U
1866ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           || e->Iex.Binop.op == Iop_CasCmpEQ32
1867ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           || e->Iex.Binop.op == Iop_CasCmpNE32)) {
1868ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HReg    r1   = iselIntExpr_R(env, e->Iex.Binop.arg1);
1869ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      X86RMI* rmi2 = iselIntExpr_RMI(env, e->Iex.Binop.arg2);
1870ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env, X86Instr_Alu32R(Xalu_CMP,rmi2,r1));
1871ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch (e->Iex.Binop.op) {
1872ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_CmpEQ32: case Iop_CasCmpEQ32: return Xcc_Z;
1873ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_CmpNE32: case Iop_CasCmpNE32: return Xcc_NZ;
1874ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_CmpLT32S: return Xcc_L;
1875ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_CmpLT32U: return Xcc_B;
1876ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_CmpLE32S: return Xcc_LE;
1877ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_CmpLE32U: return Xcc_BE;
1878ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         default: vpanic("iselCondCode(x86): CmpXX32");
1879ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1880ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1881ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1882ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* CmpNE64 */
1883ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_Binop
1884ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && (e->Iex.Binop.op == Iop_CmpNE64
1885ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           || e->Iex.Binop.op == Iop_CmpEQ64)) {
1886ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HReg hi1, hi2, lo1, lo2;
1887ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HReg tHi = newVRegI(env);
1888ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HReg tLo = newVRegI(env);
1889ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      iselInt64Expr( &hi1, &lo1, env, e->Iex.Binop.arg1 );
1890ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      iselInt64Expr( &hi2, &lo2, env, e->Iex.Binop.arg2 );
1891ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env, mk_iMOVsd_RR(hi1, tHi));
1892ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env, X86Instr_Alu32R(Xalu_XOR,X86RMI_Reg(hi2), tHi));
1893ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env, mk_iMOVsd_RR(lo1, tLo));
1894ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env, X86Instr_Alu32R(Xalu_XOR,X86RMI_Reg(lo2), tLo));
1895ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env, X86Instr_Alu32R(Xalu_OR,X86RMI_Reg(tHi), tLo));
1896ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch (e->Iex.Binop.op) {
1897ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_CmpNE64: return Xcc_NZ;
1898ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_CmpEQ64: return Xcc_Z;
1899ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         default: vpanic("iselCondCode(x86): CmpXX64");
1900ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1901ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1902ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1903ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ppIRExpr(e);
1904ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vpanic("iselCondCode");
1905ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1906ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1907ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1908ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------*/
1909ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- ISEL: Integer expressions (64 bit)                ---*/
1910ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------*/
1911ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1912ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Compute a 64-bit value into a register pair, which is returned as
1913ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   the first two parameters.  As with iselIntExpr_R, these may be
1914ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   either real or virtual regs; in any case they must not be changed
1915ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   by subsequent code emitted by the caller.  */
1916ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1917ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void iselInt64Expr ( HReg* rHi, HReg* rLo, ISelEnv* env, IRExpr* e )
1918ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1919ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   iselInt64Expr_wrk(rHi, rLo, env, e);
1920ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  if 0
1921ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vex_printf("\n"); ppIRExpr(e); vex_printf("\n");
1922ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  endif
1923ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(hregClass(*rHi) == HRcInt32);
1924ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(hregIsVirtual(*rHi));
1925ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(hregClass(*rLo) == HRcInt32);
1926ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(hregIsVirtual(*rLo));
1927ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1928ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1929ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* DO NOT CALL THIS DIRECTLY ! */
1930ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void iselInt64Expr_wrk ( HReg* rHi, HReg* rLo, ISelEnv* env, IRExpr* e )
1931ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1932ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   MatchInfo mi;
1933ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   HWord fn = 0; /* helper fn for most SIMD64 stuff */
1934ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(e);
1935ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(typeOfIRExpr(env->type_env,e) == Ity_I64);
1936ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1937ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* 64-bit literal */
1938ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_Const) {
1939ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ULong w64 = e->Iex.Const.con->Ico.U64;
1940ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt  wHi = toUInt(w64 >> 32);
1941ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt  wLo = toUInt(w64);
1942ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HReg  tLo = newVRegI(env);
1943ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HReg  tHi = newVRegI(env);
1944ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert(e->Iex.Const.con->tag == Ico_U64);
1945ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (wLo == wHi) {
1946ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Save a precious Int register in this special case. */
1947ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, X86Instr_Alu32R(Xalu_MOV, X86RMI_Imm(wLo), tLo));
1948ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *rHi = tLo;
1949ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *rLo = tLo;
1950ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else {
1951ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, X86Instr_Alu32R(Xalu_MOV, X86RMI_Imm(wHi), tHi));
1952ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, X86Instr_Alu32R(Xalu_MOV, X86RMI_Imm(wLo), tLo));
1953ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *rHi = tHi;
1954ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *rLo = tLo;
1955ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1956ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return;
1957ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1958ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1959ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* read 64-bit IRTemp */
1960ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_RdTmp) {
1961ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      lookupIRTemp64( rHi, rLo, env, e->Iex.RdTmp.tmp);
1962ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return;
1963ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1964ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1965ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* 64-bit load */
1966ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_Load && e->Iex.Load.end == Iend_LE) {
1967ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HReg     tLo, tHi;
1968ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      X86AMode *am0, *am4;
1969ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert(e->Iex.Load.ty == Ity_I64);
1970ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      tLo = newVRegI(env);
1971ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      tHi = newVRegI(env);
1972ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      am0 = iselIntExpr_AMode(env, e->Iex.Load.addr);
1973ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      am4 = advance4(am0);
1974ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env, X86Instr_Alu32R( Xalu_MOV, X86RMI_Mem(am0), tLo ));
1975ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env, X86Instr_Alu32R( Xalu_MOV, X86RMI_Mem(am4), tHi ));
1976ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *rHi = tHi;
1977ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *rLo = tLo;
1978ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return;
1979ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1980ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1981ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* 64-bit GET */
1982ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_Get) {
1983ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      X86AMode* am  = X86AMode_IR(e->Iex.Get.offset, hregX86_EBP());
1984ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      X86AMode* am4 = advance4(am);
1985ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HReg tLo = newVRegI(env);
1986ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HReg tHi = newVRegI(env);
1987ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env, X86Instr_Alu32R( Xalu_MOV, X86RMI_Mem(am), tLo ));
1988ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env, X86Instr_Alu32R( Xalu_MOV, X86RMI_Mem(am4), tHi ));
1989ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *rHi = tHi;
1990ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *rLo = tLo;
1991ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return;
1992ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1993ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1994ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* 64-bit GETI */
1995ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_GetI) {
1996ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      X86AMode* am
1997ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         = genGuestArrayOffset( env, e->Iex.GetI.descr,
1998ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                     e->Iex.GetI.ix, e->Iex.GetI.bias );
1999ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      X86AMode* am4 = advance4(am);
2000ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HReg tLo = newVRegI(env);
2001ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HReg tHi = newVRegI(env);
2002ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env, X86Instr_Alu32R( Xalu_MOV, X86RMI_Mem(am), tLo ));
2003ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env, X86Instr_Alu32R( Xalu_MOV, X86RMI_Mem(am4), tHi ));
2004ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *rHi = tHi;
2005ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *rLo = tLo;
2006ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return;
2007ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2008ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2009ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* 64-bit Mux0X: Mux0X(g, expr, 0:I64) */
2010ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_Mux0X && isZeroU64(e->Iex.Mux0X.exprX)) {
2011ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      X86RM* r8;
2012ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HReg e0Lo, e0Hi;
2013ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HReg tLo = newVRegI(env);
2014ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HReg tHi = newVRegI(env);
2015ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      X86AMode* zero_esp = X86AMode_IR(0, hregX86_ESP());
2016ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      iselInt64Expr(&e0Hi, &e0Lo, env, e->Iex.Mux0X.expr0);
2017ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      r8 = iselIntExpr_RM(env, e->Iex.Mux0X.cond);
2018ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env, mk_iMOVsd_RR( e0Hi, tHi ) );
2019ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env, mk_iMOVsd_RR( e0Lo, tLo ) );
2020ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env, X86Instr_Push(X86RMI_Imm(0)));
2021ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env, X86Instr_Test32(0xFF, r8));
2022ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env, X86Instr_CMov32(Xcc_NZ,X86RM_Mem(zero_esp),tHi));
2023ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env, X86Instr_CMov32(Xcc_NZ,X86RM_Mem(zero_esp),tLo));
2024ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      add_to_esp(env, 4);
2025ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *rHi = tHi;
2026ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *rLo = tLo;
2027ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return;
2028ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2029ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* 64-bit Mux0X: Mux0X(g, 0:I64, expr) */
2030ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_Mux0X && isZeroU64(e->Iex.Mux0X.expr0)) {
2031ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      X86RM* r8;
2032ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HReg e0Lo, e0Hi;
2033ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HReg tLo = newVRegI(env);
2034ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HReg tHi = newVRegI(env);
2035ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      X86AMode* zero_esp = X86AMode_IR(0, hregX86_ESP());
2036ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      iselInt64Expr(&e0Hi, &e0Lo, env, e->Iex.Mux0X.exprX);
2037ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      r8 = iselIntExpr_RM(env, e->Iex.Mux0X.cond);
2038ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env, mk_iMOVsd_RR( e0Hi, tHi ) );
2039ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env, mk_iMOVsd_RR( e0Lo, tLo ) );
2040ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env, X86Instr_Push(X86RMI_Imm(0)));
2041ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env, X86Instr_Test32(0xFF, r8));
2042ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env, X86Instr_CMov32(Xcc_Z,X86RM_Mem(zero_esp),tHi));
2043ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env, X86Instr_CMov32(Xcc_Z,X86RM_Mem(zero_esp),tLo));
2044ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      add_to_esp(env, 4);
2045ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *rHi = tHi;
2046ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *rLo = tLo;
2047ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return;
2048ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2049ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2050ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* 64-bit Mux0X: Mux0X(g, expr, expr) */
2051ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_Mux0X) {
2052ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      X86RM* r8;
2053ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HReg e0Lo, e0Hi, eXLo, eXHi;
2054ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HReg tLo = newVRegI(env);
2055ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HReg tHi = newVRegI(env);
2056ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      iselInt64Expr(&e0Hi, &e0Lo, env, e->Iex.Mux0X.expr0);
2057ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      iselInt64Expr(&eXHi, &eXLo, env, e->Iex.Mux0X.exprX);
2058ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env, mk_iMOVsd_RR(eXHi, tHi));
2059ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env, mk_iMOVsd_RR(eXLo, tLo));
2060ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      r8 = iselIntExpr_RM(env, e->Iex.Mux0X.cond);
2061ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env, X86Instr_Test32(0xFF, r8));
2062ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* This assumes the first cmov32 doesn't trash the condition
2063ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         codes, so they are still available for the second cmov32 */
2064ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env, X86Instr_CMov32(Xcc_Z,X86RM_Reg(e0Hi),tHi));
2065ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env, X86Instr_CMov32(Xcc_Z,X86RM_Reg(e0Lo),tLo));
2066ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *rHi = tHi;
2067ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *rLo = tLo;
2068ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return;
2069ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2070ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2071ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* --------- BINARY ops --------- */
2072ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_Binop) {
2073ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch (e->Iex.Binop.op) {
2074ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* 32 x 32 -> 64 multiply */
2075ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_MullU32:
2076ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_MullS32: {
2077ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* get one operand into %eax, and the other into a R/M.
2078ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               Need to make an educated guess about which is better in
2079ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               which. */
2080ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg   tLo    = newVRegI(env);
2081ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg   tHi    = newVRegI(env);
2082ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            Bool   syned  = toBool(e->Iex.Binop.op == Iop_MullS32);
2083ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            X86RM* rmLeft = iselIntExpr_RM(env, e->Iex.Binop.arg1);
2084ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg   rRight = iselIntExpr_R(env, e->Iex.Binop.arg2);
2085ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, mk_iMOVsd_RR(rRight, hregX86_EAX()));
2086ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, X86Instr_MulL(syned, rmLeft));
2087ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* Result is now in EDX:EAX.  Tell the caller. */
2088ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, mk_iMOVsd_RR(hregX86_EDX(), tHi));
2089ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, mk_iMOVsd_RR(hregX86_EAX(), tLo));
2090ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            *rHi = tHi;
2091ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            *rLo = tLo;
2092ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return;
2093ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
2094ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2095ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* 64 x 32 -> (32(rem),32(div)) division */
2096ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_DivModU64to32:
2097ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_DivModS64to32: {
2098ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* Get the 64-bit operand into edx:eax, and the other into
2099ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               any old R/M. */
2100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg sHi, sLo;
2101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg   tLo     = newVRegI(env);
2102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg   tHi     = newVRegI(env);
2103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            Bool   syned   = toBool(e->Iex.Binop.op == Iop_DivModS64to32);
2104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            X86RM* rmRight = iselIntExpr_RM(env, e->Iex.Binop.arg2);
2105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            iselInt64Expr(&sHi,&sLo, env, e->Iex.Binop.arg1);
2106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, mk_iMOVsd_RR(sHi, hregX86_EDX()));
2107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, mk_iMOVsd_RR(sLo, hregX86_EAX()));
2108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, X86Instr_Div(syned, rmRight));
2109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, mk_iMOVsd_RR(hregX86_EDX(), tHi));
2110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, mk_iMOVsd_RR(hregX86_EAX(), tLo));
2111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            *rHi = tHi;
2112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            *rLo = tLo;
2113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return;
2114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
2115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Or64/And64/Xor64 */
2117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_Or64:
2118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_And64:
2119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_Xor64: {
2120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg xLo, xHi, yLo, yHi;
2121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg tLo = newVRegI(env);
2122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg tHi = newVRegI(env);
2123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            X86AluOp op = e->Iex.Binop.op==Iop_Or64 ? Xalu_OR
2124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          : e->Iex.Binop.op==Iop_And64 ? Xalu_AND
2125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          : Xalu_XOR;
2126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            iselInt64Expr(&xHi, &xLo, env, e->Iex.Binop.arg1);
2127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            iselInt64Expr(&yHi, &yLo, env, e->Iex.Binop.arg2);
2128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, mk_iMOVsd_RR(xHi, tHi));
2129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, X86Instr_Alu32R(op, X86RMI_Reg(yHi), tHi));
2130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, mk_iMOVsd_RR(xLo, tLo));
2131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, X86Instr_Alu32R(op, X86RMI_Reg(yLo), tLo));
2132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            *rHi = tHi;
2133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            *rLo = tLo;
2134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return;
2135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
2136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Add64/Sub64 */
2138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_Add64:
2139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (e->Iex.Binop.arg2->tag == Iex_Const) {
2140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               /* special case Add64(e, const) */
2141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               ULong w64 = e->Iex.Binop.arg2->Iex.Const.con->Ico.U64;
2142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               UInt  wHi = toUInt(w64 >> 32);
2143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               UInt  wLo = toUInt(w64);
2144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               HReg  tLo = newVRegI(env);
2145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               HReg  tHi = newVRegI(env);
2146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               HReg  xLo, xHi;
2147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               vassert(e->Iex.Binop.arg2->Iex.Const.con->tag == Ico_U64);
2148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               iselInt64Expr(&xHi, &xLo, env, e->Iex.Binop.arg1);
2149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               addInstr(env, mk_iMOVsd_RR(xHi, tHi));
2150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               addInstr(env, mk_iMOVsd_RR(xLo, tLo));
2151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               addInstr(env, X86Instr_Alu32R(Xalu_ADD, X86RMI_Imm(wLo), tLo));
2152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               addInstr(env, X86Instr_Alu32R(Xalu_ADC, X86RMI_Imm(wHi), tHi));
2153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               *rHi = tHi;
2154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               *rLo = tLo;
2155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               return;
2156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
2157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* else fall through to the generic case */
2158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_Sub64: {
2159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg xLo, xHi, yLo, yHi;
2160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg tLo = newVRegI(env);
2161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg tHi = newVRegI(env);
2162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            iselInt64Expr(&xHi, &xLo, env, e->Iex.Binop.arg1);
2163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, mk_iMOVsd_RR(xHi, tHi));
2164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, mk_iMOVsd_RR(xLo, tLo));
2165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            iselInt64Expr(&yHi, &yLo, env, e->Iex.Binop.arg2);
2166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (e->Iex.Binop.op==Iop_Add64) {
2167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               addInstr(env, X86Instr_Alu32R(Xalu_ADD, X86RMI_Reg(yLo), tLo));
2168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               addInstr(env, X86Instr_Alu32R(Xalu_ADC, X86RMI_Reg(yHi), tHi));
2169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else {
2170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               addInstr(env, X86Instr_Alu32R(Xalu_SUB, X86RMI_Reg(yLo), tLo));
2171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               addInstr(env, X86Instr_Alu32R(Xalu_SBB, X86RMI_Reg(yHi), tHi));
2172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
2173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            *rHi = tHi;
2174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            *rLo = tLo;
2175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return;
2176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
2177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* 32HLto64(e1,e2) */
2179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_32HLto64:
2180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            *rHi = iselIntExpr_R(env, e->Iex.Binop.arg1);
2181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            *rLo = iselIntExpr_R(env, e->Iex.Binop.arg2);
2182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return;
2183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* 64-bit shifts */
2185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_Shl64: {
2186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* We use the same ingenious scheme as gcc.  Put the value
2187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               to be shifted into %hi:%lo, and the shift amount into
2188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               %cl.  Then (dsts on right, a la ATT syntax):
2189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               shldl %cl, %lo, %hi   -- make %hi be right for the
2191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                     -- shift amt %cl % 32
2192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               shll  %cl, %lo        -- make %lo be right for the
2193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                     -- shift amt %cl % 32
2194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               Now, if (shift amount % 64) is in the range 32 .. 63,
2196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               we have to do a fixup, which puts the result low half
2197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               into the result high half, and zeroes the low half:
2198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               testl $32, %ecx
2200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               cmovnz %lo, %hi
2202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               movl $0, %tmp         -- sigh; need yet another reg
2203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               cmovnz %tmp, %lo
2204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            */
2205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg rAmt, sHi, sLo, tHi, tLo, tTemp;
2206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            tLo = newVRegI(env);
2207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            tHi = newVRegI(env);
2208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            tTemp = newVRegI(env);
2209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            rAmt = iselIntExpr_R(env, e->Iex.Binop.arg2);
2210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            iselInt64Expr(&sHi,&sLo, env, e->Iex.Binop.arg1);
2211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, mk_iMOVsd_RR(rAmt, hregX86_ECX()));
2212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, mk_iMOVsd_RR(sHi, tHi));
2213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, mk_iMOVsd_RR(sLo, tLo));
2214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* Ok.  Now shift amt is in %ecx, and value is in tHi/tLo
2215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               and those regs are legitimately modifiable. */
2216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, X86Instr_Sh3232(Xsh_SHL, 0/*%cl*/, tLo, tHi));
2217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, X86Instr_Sh32(Xsh_SHL, 0/*%cl*/, tLo));
2218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, X86Instr_Test32(32, X86RM_Reg(hregX86_ECX())));
2219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, X86Instr_CMov32(Xcc_NZ, X86RM_Reg(tLo), tHi));
2220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, X86Instr_Alu32R(Xalu_MOV, X86RMI_Imm(0), tTemp));
2221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, X86Instr_CMov32(Xcc_NZ, X86RM_Reg(tTemp), tLo));
2222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            *rHi = tHi;
2223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            *rLo = tLo;
2224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return;
2225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
2226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_Shr64: {
2228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* We use the same ingenious scheme as gcc.  Put the value
2229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               to be shifted into %hi:%lo, and the shift amount into
2230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               %cl.  Then:
2231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               shrdl %cl, %hi, %lo   -- make %lo be right for the
2233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                     -- shift amt %cl % 32
2234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               shrl  %cl, %hi        -- make %hi be right for the
2235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                     -- shift amt %cl % 32
2236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               Now, if (shift amount % 64) is in the range 32 .. 63,
2238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               we have to do a fixup, which puts the result high half
2239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               into the result low half, and zeroes the high half:
2240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               testl $32, %ecx
2242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               cmovnz %hi, %lo
2244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               movl $0, %tmp         -- sigh; need yet another reg
2245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               cmovnz %tmp, %hi
2246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            */
2247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg rAmt, sHi, sLo, tHi, tLo, tTemp;
2248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            tLo = newVRegI(env);
2249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            tHi = newVRegI(env);
2250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            tTemp = newVRegI(env);
2251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            rAmt = iselIntExpr_R(env, e->Iex.Binop.arg2);
2252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            iselInt64Expr(&sHi,&sLo, env, e->Iex.Binop.arg1);
2253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, mk_iMOVsd_RR(rAmt, hregX86_ECX()));
2254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, mk_iMOVsd_RR(sHi, tHi));
2255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, mk_iMOVsd_RR(sLo, tLo));
2256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* Ok.  Now shift amt is in %ecx, and value is in tHi/tLo
2257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               and those regs are legitimately modifiable. */
2258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, X86Instr_Sh3232(Xsh_SHR, 0/*%cl*/, tHi, tLo));
2259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, X86Instr_Sh32(Xsh_SHR, 0/*%cl*/, tHi));
2260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, X86Instr_Test32(32, X86RM_Reg(hregX86_ECX())));
2261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, X86Instr_CMov32(Xcc_NZ, X86RM_Reg(tHi), tLo));
2262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, X86Instr_Alu32R(Xalu_MOV, X86RMI_Imm(0), tTemp));
2263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, X86Instr_CMov32(Xcc_NZ, X86RM_Reg(tTemp), tHi));
2264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            *rHi = tHi;
2265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            *rLo = tLo;
2266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return;
2267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
2268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* F64 -> I64 */
2270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Sigh, this is an almost exact copy of the F64 -> I32/I16
2271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case.  Unfortunately I see no easy way to avoid the
2272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            duplication. */
2273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_F64toI64S: {
2274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg rf  = iselDblExpr(env, e->Iex.Binop.arg2);
2275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg tLo = newVRegI(env);
2276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg tHi = newVRegI(env);
2277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* Used several times ... */
2279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* Careful ... this sharing is only safe because
2280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	       zero_esp/four_esp do not hold any registers which the
2281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	       register allocator could attempt to swizzle later. */
2282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            X86AMode* zero_esp = X86AMode_IR(0, hregX86_ESP());
2283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            X86AMode* four_esp = X86AMode_IR(4, hregX86_ESP());
2284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* rf now holds the value to be converted, and rrm holds
2286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               the rounding mode value, encoded as per the
2287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               IRRoundingMode enum.  The first thing to do is set the
2288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               FPU's rounding mode accordingly. */
2289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* Create a space for the format conversion. */
2291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* subl $8, %esp */
2292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            sub_from_esp(env, 8);
2293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* Set host rounding mode */
2295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            set_FPU_rounding_mode( env, e->Iex.Binop.arg1 );
2296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* gistll %rf, 0(%esp) */
2298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, X86Instr_FpLdStI(False/*store*/, 8, rf, zero_esp));
2299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* movl 0(%esp), %dstLo */
2301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* movl 4(%esp), %dstHi */
2302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, X86Instr_Alu32R(
2303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             Xalu_MOV, X86RMI_Mem(zero_esp), tLo));
2304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, X86Instr_Alu32R(
2305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             Xalu_MOV, X86RMI_Mem(four_esp), tHi));
2306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* Restore default FPU rounding. */
2308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            set_FPU_rounding_default( env );
2309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* addl $8, %esp */
2311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            add_to_esp(env, 8);
2312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            *rHi = tHi;
2314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            *rLo = tLo;
2315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return;
2316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
2317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_Add8x8:
2319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            fn = (HWord)h_generic_calc_Add8x8; goto binnish;
2320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_Add16x4:
2321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            fn = (HWord)h_generic_calc_Add16x4; goto binnish;
2322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_Add32x2:
2323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            fn = (HWord)h_generic_calc_Add32x2; goto binnish;
2324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_Avg8Ux8:
2326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            fn = (HWord)h_generic_calc_Avg8Ux8; goto binnish;
2327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_Avg16Ux4:
2328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            fn = (HWord)h_generic_calc_Avg16Ux4; goto binnish;
2329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_CmpEQ8x8:
2331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            fn = (HWord)h_generic_calc_CmpEQ8x8; goto binnish;
2332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_CmpEQ16x4:
2333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            fn = (HWord)h_generic_calc_CmpEQ16x4; goto binnish;
2334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_CmpEQ32x2:
2335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            fn = (HWord)h_generic_calc_CmpEQ32x2; goto binnish;
2336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_CmpGT8Sx8:
2338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            fn = (HWord)h_generic_calc_CmpGT8Sx8; goto binnish;
2339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_CmpGT16Sx4:
2340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            fn = (HWord)h_generic_calc_CmpGT16Sx4; goto binnish;
2341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_CmpGT32Sx2:
2342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            fn = (HWord)h_generic_calc_CmpGT32Sx2; goto binnish;
2343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_InterleaveHI8x8:
2345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            fn = (HWord)h_generic_calc_InterleaveHI8x8; goto binnish;
2346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_InterleaveLO8x8:
2347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            fn = (HWord)h_generic_calc_InterleaveLO8x8; goto binnish;
2348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_InterleaveHI16x4:
2349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            fn = (HWord)h_generic_calc_InterleaveHI16x4; goto binnish;
2350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_InterleaveLO16x4:
2351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            fn = (HWord)h_generic_calc_InterleaveLO16x4; goto binnish;
2352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_InterleaveHI32x2:
2353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            fn = (HWord)h_generic_calc_InterleaveHI32x2; goto binnish;
2354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_InterleaveLO32x2:
2355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            fn = (HWord)h_generic_calc_InterleaveLO32x2; goto binnish;
2356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_CatOddLanes16x4:
2357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            fn = (HWord)h_generic_calc_CatOddLanes16x4; goto binnish;
2358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_CatEvenLanes16x4:
2359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            fn = (HWord)h_generic_calc_CatEvenLanes16x4; goto binnish;
2360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_Perm8x8:
2361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            fn = (HWord)h_generic_calc_Perm8x8; goto binnish;
2362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_Max8Ux8:
2364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            fn = (HWord)h_generic_calc_Max8Ux8; goto binnish;
2365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_Max16Sx4:
2366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            fn = (HWord)h_generic_calc_Max16Sx4; goto binnish;
2367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_Min8Ux8:
2368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            fn = (HWord)h_generic_calc_Min8Ux8; goto binnish;
2369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_Min16Sx4:
2370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            fn = (HWord)h_generic_calc_Min16Sx4; goto binnish;
2371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_Mul16x4:
2373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            fn = (HWord)h_generic_calc_Mul16x4; goto binnish;
2374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_Mul32x2:
2375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            fn = (HWord)h_generic_calc_Mul32x2; goto binnish;
2376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_MulHi16Sx4:
2377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            fn = (HWord)h_generic_calc_MulHi16Sx4; goto binnish;
2378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_MulHi16Ux4:
2379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            fn = (HWord)h_generic_calc_MulHi16Ux4; goto binnish;
2380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_QAdd8Sx8:
2382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            fn = (HWord)h_generic_calc_QAdd8Sx8; goto binnish;
2383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_QAdd16Sx4:
2384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            fn = (HWord)h_generic_calc_QAdd16Sx4; goto binnish;
2385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_QAdd8Ux8:
2386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            fn = (HWord)h_generic_calc_QAdd8Ux8; goto binnish;
2387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_QAdd16Ux4:
2388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            fn = (HWord)h_generic_calc_QAdd16Ux4; goto binnish;
2389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2390b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         case Iop_QNarrowBin32Sto16Sx4:
2391b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            fn = (HWord)h_generic_calc_QNarrowBin32Sto16Sx4; goto binnish;
2392b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         case Iop_QNarrowBin16Sto8Sx8:
2393b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            fn = (HWord)h_generic_calc_QNarrowBin16Sto8Sx8; goto binnish;
2394b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         case Iop_QNarrowBin16Sto8Ux8:
2395b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            fn = (HWord)h_generic_calc_QNarrowBin16Sto8Ux8; goto binnish;
2396b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         case Iop_NarrowBin16to8x8:
2397b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            fn = (HWord)h_generic_calc_NarrowBin16to8x8; goto binnish;
2398b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         case Iop_NarrowBin32to16x4:
2399b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            fn = (HWord)h_generic_calc_NarrowBin32to16x4; goto binnish;
2400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_QSub8Sx8:
2402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            fn = (HWord)h_generic_calc_QSub8Sx8; goto binnish;
2403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_QSub16Sx4:
2404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            fn = (HWord)h_generic_calc_QSub16Sx4; goto binnish;
2405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_QSub8Ux8:
2406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            fn = (HWord)h_generic_calc_QSub8Ux8; goto binnish;
2407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_QSub16Ux4:
2408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            fn = (HWord)h_generic_calc_QSub16Ux4; goto binnish;
2409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_Sub8x8:
2411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            fn = (HWord)h_generic_calc_Sub8x8; goto binnish;
2412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_Sub16x4:
2413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            fn = (HWord)h_generic_calc_Sub16x4; goto binnish;
2414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_Sub32x2:
2415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            fn = (HWord)h_generic_calc_Sub32x2; goto binnish;
2416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         binnish: {
2418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* Note: the following assumes all helpers are of
2419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               signature
2420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  ULong fn ( ULong, ULong ), and they are
2421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               not marked as regparm functions.
2422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            */
2423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg xLo, xHi, yLo, yHi;
2424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg tLo = newVRegI(env);
2425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg tHi = newVRegI(env);
2426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            iselInt64Expr(&yHi, &yLo, env, e->Iex.Binop.arg2);
2427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, X86Instr_Push(X86RMI_Reg(yHi)));
2428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, X86Instr_Push(X86RMI_Reg(yLo)));
2429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            iselInt64Expr(&xHi, &xLo, env, e->Iex.Binop.arg1);
2430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, X86Instr_Push(X86RMI_Reg(xHi)));
2431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, X86Instr_Push(X86RMI_Reg(xLo)));
2432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, X86Instr_Call( Xcc_ALWAYS, (UInt)fn, 0 ));
2433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            add_to_esp(env, 4*4);
2434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, mk_iMOVsd_RR(hregX86_EDX(), tHi));
2435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, mk_iMOVsd_RR(hregX86_EAX(), tLo));
2436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            *rHi = tHi;
2437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            *rLo = tLo;
2438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return;
2439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
2440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_ShlN32x2:
2442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            fn = (HWord)h_generic_calc_ShlN32x2; goto shifty;
2443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_ShlN16x4:
2444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            fn = (HWord)h_generic_calc_ShlN16x4; goto shifty;
2445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_ShlN8x8:
2446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            fn = (HWord)h_generic_calc_ShlN8x8;  goto shifty;
2447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_ShrN32x2:
2448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            fn = (HWord)h_generic_calc_ShrN32x2; goto shifty;
2449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_ShrN16x4:
2450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            fn = (HWord)h_generic_calc_ShrN16x4; goto shifty;
2451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_SarN32x2:
2452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            fn = (HWord)h_generic_calc_SarN32x2; goto shifty;
2453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_SarN16x4:
2454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            fn = (HWord)h_generic_calc_SarN16x4; goto shifty;
2455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_SarN8x8:
2456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            fn = (HWord)h_generic_calc_SarN8x8;  goto shifty;
2457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         shifty: {
2458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* Note: the following assumes all helpers are of
2459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               signature
2460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  ULong fn ( ULong, UInt ), and they are
2461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               not marked as regparm functions.
2462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            */
2463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg xLo, xHi;
2464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg tLo = newVRegI(env);
2465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg tHi = newVRegI(env);
2466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            X86RMI* y = iselIntExpr_RMI(env, e->Iex.Binop.arg2);
2467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, X86Instr_Push(y));
2468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            iselInt64Expr(&xHi, &xLo, env, e->Iex.Binop.arg1);
2469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, X86Instr_Push(X86RMI_Reg(xHi)));
2470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, X86Instr_Push(X86RMI_Reg(xLo)));
2471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, X86Instr_Call( Xcc_ALWAYS, (UInt)fn, 0 ));
2472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            add_to_esp(env, 3*4);
2473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, mk_iMOVsd_RR(hregX86_EDX(), tHi));
2474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, mk_iMOVsd_RR(hregX86_EAX(), tLo));
2475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            *rHi = tHi;
2476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            *rLo = tLo;
2477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return;
2478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
2479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         default:
2481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
2482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } /* if (e->tag == Iex_Binop) */
2484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* --------- UNARY ops --------- */
2487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_Unop) {
2488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch (e->Iex.Unop.op) {
2489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* 32Sto64(e) */
2491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_32Sto64: {
2492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg tLo = newVRegI(env);
2493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg tHi = newVRegI(env);
2494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg src = iselIntExpr_R(env, e->Iex.Unop.arg);
2495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, mk_iMOVsd_RR(src,tHi));
2496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, mk_iMOVsd_RR(src,tLo));
2497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, X86Instr_Sh32(Xsh_SAR, 31, tHi));
2498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            *rHi = tHi;
2499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            *rLo = tLo;
2500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return;
2501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
2502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* 32Uto64(e) */
2504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_32Uto64: {
2505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg tLo = newVRegI(env);
2506ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg tHi = newVRegI(env);
2507ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg src = iselIntExpr_R(env, e->Iex.Unop.arg);
2508ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, mk_iMOVsd_RR(src,tLo));
2509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, X86Instr_Alu32R(Xalu_MOV, X86RMI_Imm(0), tHi));
2510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            *rHi = tHi;
2511ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            *rLo = tLo;
2512ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return;
2513ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
2514ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2515ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* 16Uto64(e) */
2516ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_16Uto64: {
2517ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg tLo = newVRegI(env);
2518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg tHi = newVRegI(env);
2519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg src = iselIntExpr_R(env, e->Iex.Unop.arg);
2520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, mk_iMOVsd_RR(src,tLo));
2521ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, X86Instr_Alu32R(Xalu_AND,
2522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                          X86RMI_Imm(0xFFFF), tLo));
2523ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, X86Instr_Alu32R(Xalu_MOV, X86RMI_Imm(0), tHi));
2524ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            *rHi = tHi;
2525ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            *rLo = tLo;
2526ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return;
2527ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
2528ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2529ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* V128{HI}to64 */
2530ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_V128HIto64:
2531ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_V128to64: {
2532ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            Int  off = e->Iex.Unop.op==Iop_V128HIto64 ? 8 : 0;
2533ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg tLo = newVRegI(env);
2534ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg tHi = newVRegI(env);
2535ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg vec = iselVecExpr(env, e->Iex.Unop.arg);
2536ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            X86AMode* esp0  = X86AMode_IR(0,     hregX86_ESP());
2537ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            X86AMode* espLO = X86AMode_IR(off,   hregX86_ESP());
2538ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            X86AMode* espHI = X86AMode_IR(off+4, hregX86_ESP());
2539ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            sub_from_esp(env, 16);
2540ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, X86Instr_SseLdSt(False/*store*/, vec, esp0));
2541ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, X86Instr_Alu32R( Xalu_MOV,
2542ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                           X86RMI_Mem(espLO), tLo ));
2543ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, X86Instr_Alu32R( Xalu_MOV,
2544ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                           X86RMI_Mem(espHI), tHi ));
2545ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            add_to_esp(env, 16);
2546ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            *rHi = tHi;
2547ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            *rLo = tLo;
2548ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return;
2549ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
2550ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2551ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* could do better than this, but for now ... */
2552ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_1Sto64: {
2553ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg tLo = newVRegI(env);
2554ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg tHi = newVRegI(env);
2555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            X86CondCode cond = iselCondCode(env, e->Iex.Unop.arg);
2556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, X86Instr_Set32(cond,tLo));
2557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, X86Instr_Sh32(Xsh_SHL, 31, tLo));
2558ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, X86Instr_Sh32(Xsh_SAR, 31, tLo));
2559ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, mk_iMOVsd_RR(tLo, tHi));
2560ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            *rHi = tHi;
2561ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            *rLo = tLo;
2562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return;
2563ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
2564ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2565ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Not64(e) */
2566ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_Not64: {
2567ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg tLo = newVRegI(env);
2568ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg tHi = newVRegI(env);
2569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg sHi, sLo;
2570ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            iselInt64Expr(&sHi, &sLo, env, e->Iex.Unop.arg);
2571ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, mk_iMOVsd_RR(sHi, tHi));
2572ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, mk_iMOVsd_RR(sLo, tLo));
2573ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, X86Instr_Unary32(Xun_NOT,tHi));
2574ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, X86Instr_Unary32(Xun_NOT,tLo));
2575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            *rHi = tHi;
2576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            *rLo = tLo;
2577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return;
2578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
2579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Left64(e) */
2581ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_Left64: {
2582ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg yLo, yHi;
2583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg tLo = newVRegI(env);
2584ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg tHi = newVRegI(env);
2585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* yHi:yLo = arg */
2586ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            iselInt64Expr(&yHi, &yLo, env, e->Iex.Unop.arg);
2587ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* tLo = 0 - yLo, and set carry */
2588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, X86Instr_Alu32R(Xalu_MOV, X86RMI_Imm(0), tLo));
2589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, X86Instr_Alu32R(Xalu_SUB, X86RMI_Reg(yLo), tLo));
2590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* tHi = 0 - yHi - carry */
2591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, X86Instr_Alu32R(Xalu_MOV, X86RMI_Imm(0), tHi));
2592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, X86Instr_Alu32R(Xalu_SBB, X86RMI_Reg(yHi), tHi));
2593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* So now we have tHi:tLo = -arg.  To finish off, or 'arg'
2594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               back in, so as to give the final result
2595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               tHi:tLo = arg | -arg. */
2596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, X86Instr_Alu32R(Xalu_OR, X86RMI_Reg(yLo), tLo));
2597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, X86Instr_Alu32R(Xalu_OR, X86RMI_Reg(yHi), tHi));
2598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            *rHi = tHi;
2599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            *rLo = tLo;
2600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return;
2601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
2602ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* --- patterns rooted at: CmpwNEZ64 --- */
2604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2605ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* CmpwNEZ64(e) */
2606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_CmpwNEZ64: {
2607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2608ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DECLARE_PATTERN(p_CmpwNEZ64_Or64);
2609ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DEFINE_PATTERN(p_CmpwNEZ64_Or64,
2610ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        unop(Iop_CmpwNEZ64,binop(Iop_Or64,bind(0),bind(1))));
2611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (matchIRExpr(&mi, p_CmpwNEZ64_Or64, e)) {
2612ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* CmpwNEZ64(Or64(x,y)) */
2613ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg xHi,xLo,yHi,yLo;
2614ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg xBoth = newVRegI(env);
2615ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg merged = newVRegI(env);
2616ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg tmp2 = newVRegI(env);
2617ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2618ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            iselInt64Expr(&xHi,&xLo, env, mi.bindee[0]);
2619ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, mk_iMOVsd_RR(xHi,xBoth));
2620ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, X86Instr_Alu32R(Xalu_OR,
2621ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                          X86RMI_Reg(xLo),xBoth));
2622ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2623ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            iselInt64Expr(&yHi,&yLo, env, mi.bindee[1]);
2624ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, mk_iMOVsd_RR(yHi,merged));
2625ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, X86Instr_Alu32R(Xalu_OR,
2626ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                          X86RMI_Reg(yLo),merged));
2627ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, X86Instr_Alu32R(Xalu_OR,
2628ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                             X86RMI_Reg(xBoth),merged));
2629ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2630ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* tmp2 = (merged | -merged) >>s 31 */
2631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, mk_iMOVsd_RR(merged,tmp2));
2632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, X86Instr_Unary32(Xun_NEG,tmp2));
2633ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, X86Instr_Alu32R(Xalu_OR,
2634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                          X86RMI_Reg(merged), tmp2));
2635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, X86Instr_Sh32(Xsh_SAR, 31, tmp2));
2636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            *rHi = tmp2;
2637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            *rLo = tmp2;
2638ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return;
2639ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
2640ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* CmpwNEZ64(e) */
2641ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg srcLo, srcHi;
2642ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg tmp1  = newVRegI(env);
2643ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg tmp2  = newVRegI(env);
2644ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* srcHi:srcLo = arg */
2645ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            iselInt64Expr(&srcHi, &srcLo, env, e->Iex.Unop.arg);
2646ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* tmp1 = srcHi | srcLo */
2647ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, mk_iMOVsd_RR(srcHi,tmp1));
2648ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, X86Instr_Alu32R(Xalu_OR,
2649ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                          X86RMI_Reg(srcLo), tmp1));
2650ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* tmp2 = (tmp1 | -tmp1) >>s 31 */
2651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, mk_iMOVsd_RR(tmp1,tmp2));
2652ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, X86Instr_Unary32(Xun_NEG,tmp2));
2653ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, X86Instr_Alu32R(Xalu_OR,
2654ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                          X86RMI_Reg(tmp1), tmp2));
2655ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, X86Instr_Sh32(Xsh_SAR, 31, tmp2));
2656ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            *rHi = tmp2;
2657ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            *rLo = tmp2;
2658ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return;
2659ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
2660ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
2661ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2662ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* ReinterpF64asI64(e) */
2663ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Given an IEEE754 double, produce an I64 with the same bit
2664ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            pattern. */
2665ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_ReinterpF64asI64: {
2666ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg rf   = iselDblExpr(env, e->Iex.Unop.arg);
2667ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg tLo  = newVRegI(env);
2668ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg tHi  = newVRegI(env);
2669ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            X86AMode* zero_esp = X86AMode_IR(0, hregX86_ESP());
2670ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            X86AMode* four_esp = X86AMode_IR(4, hregX86_ESP());
2671ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* paranoia */
2672ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            set_FPU_rounding_default(env);
2673ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* subl $8, %esp */
2674ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            sub_from_esp(env, 8);
2675ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* gstD %rf, 0(%esp) */
2676ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env,
2677ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     X86Instr_FpLdSt(False/*store*/, 8, rf, zero_esp));
2678ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* movl 0(%esp), %tLo */
2679ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env,
2680ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     X86Instr_Alu32R(Xalu_MOV, X86RMI_Mem(zero_esp), tLo));
2681ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* movl 4(%esp), %tHi */
2682ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env,
2683ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     X86Instr_Alu32R(Xalu_MOV, X86RMI_Mem(four_esp), tHi));
2684ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* addl $8, %esp */
2685ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            add_to_esp(env, 8);
2686ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            *rHi = tHi;
2687ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            *rLo = tLo;
2688ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return;
2689ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
2690ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2691ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_CmpNEZ32x2:
2692ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            fn = (HWord)h_generic_calc_CmpNEZ32x2; goto unish;
2693ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_CmpNEZ16x4:
2694ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            fn = (HWord)h_generic_calc_CmpNEZ16x4; goto unish;
2695ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_CmpNEZ8x8:
2696ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            fn = (HWord)h_generic_calc_CmpNEZ8x8; goto unish;
2697ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         unish: {
2698ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* Note: the following assumes all helpers are of
2699ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               signature
2700ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  ULong fn ( ULong ), and they are
2701ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               not marked as regparm functions.
2702ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            */
2703ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg xLo, xHi;
2704ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg tLo = newVRegI(env);
2705ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg tHi = newVRegI(env);
2706ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            iselInt64Expr(&xHi, &xLo, env, e->Iex.Unop.arg);
2707ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, X86Instr_Push(X86RMI_Reg(xHi)));
2708ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, X86Instr_Push(X86RMI_Reg(xLo)));
2709ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, X86Instr_Call( Xcc_ALWAYS, (UInt)fn, 0 ));
2710ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            add_to_esp(env, 2*4);
2711ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, mk_iMOVsd_RR(hregX86_EDX(), tHi));
2712ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, mk_iMOVsd_RR(hregX86_EAX(), tLo));
2713ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            *rHi = tHi;
2714ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            *rLo = tLo;
2715ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return;
2716ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
2717ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2718ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         default:
2719ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
2720ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2721ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } /* if (e->tag == Iex_Unop) */
2722ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2723ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2724ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* --------- CCALL --------- */
2725ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_CCall) {
2726ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HReg tLo = newVRegI(env);
2727ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HReg tHi = newVRegI(env);
2728ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2729ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Marshal args, do the call, clear stack. */
2730ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      doHelperCall( env, False, NULL, e->Iex.CCall.cee, e->Iex.CCall.args );
2731ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2732ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env, mk_iMOVsd_RR(hregX86_EDX(), tHi));
2733ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env, mk_iMOVsd_RR(hregX86_EAX(), tLo));
2734ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *rHi = tHi;
2735ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *rLo = tLo;
2736ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return;
2737ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2738ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2739ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ppIRExpr(e);
2740ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vpanic("iselInt64Expr");
2741ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2742ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2743ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2744ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------*/
2745ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- ISEL: Floating point expressions (32 bit)         ---*/
2746ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------*/
2747ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2748ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Nothing interesting here; really just wrappers for
2749ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   64-bit stuff. */
2750ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2751ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic HReg iselFltExpr ( ISelEnv* env, IRExpr* e )
2752ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2753ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   HReg r = iselFltExpr_wrk( env, e );
2754ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  if 0
2755ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vex_printf("\n"); ppIRExpr(e); vex_printf("\n");
2756ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  endif
2757ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(hregClass(r) == HRcFlt64); /* yes, really Flt64 */
2758ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(hregIsVirtual(r));
2759ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return r;
2760ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2761ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2762ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* DO NOT CALL THIS DIRECTLY */
2763ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic HReg iselFltExpr_wrk ( ISelEnv* env, IRExpr* e )
2764ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2765ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRType ty = typeOfIRExpr(env->type_env,e);
2766ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(ty == Ity_F32);
2767ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2768ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_RdTmp) {
2769ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return lookupIRTemp(env, e->Iex.RdTmp.tmp);
2770ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2771ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2772ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_Load && e->Iex.Load.end == Iend_LE) {
2773ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      X86AMode* am;
2774ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HReg res = newVRegF(env);
2775ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert(e->Iex.Load.ty == Ity_F32);
2776ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      am = iselIntExpr_AMode(env, e->Iex.Load.addr);
2777ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env, X86Instr_FpLdSt(True/*load*/, 4, res, am));
2778ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return res;
2779ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2780ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2781ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_Binop
2782ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && e->Iex.Binop.op == Iop_F64toF32) {
2783ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Although the result is still held in a standard FPU register,
2784ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         we need to round it to reflect the loss of accuracy/range
2785ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         entailed in casting it to a 32-bit float. */
2786ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HReg dst = newVRegF(env);
2787ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HReg src = iselDblExpr(env, e->Iex.Binop.arg2);
2788ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      set_FPU_rounding_mode( env, e->Iex.Binop.arg1 );
2789ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env, X86Instr_Fp64to32(src,dst));
2790ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      set_FPU_rounding_default( env );
2791ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return dst;
2792ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2793ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2794ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_Get) {
2795ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      X86AMode* am = X86AMode_IR( e->Iex.Get.offset,
2796ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                  hregX86_EBP() );
2797ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HReg res = newVRegF(env);
2798ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env, X86Instr_FpLdSt( True/*load*/, 4, res, am ));
2799ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return res;
2800ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2801ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2802ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_Unop
2803ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && e->Iex.Unop.op == Iop_ReinterpI32asF32) {
2804ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       /* Given an I32, produce an IEEE754 float with the same bit
2805ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          pattern. */
2806ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HReg    dst = newVRegF(env);
2807ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      X86RMI* rmi = iselIntExpr_RMI(env, e->Iex.Unop.arg);
2808ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* paranoia */
2809ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env, X86Instr_Push(rmi));
2810ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env, X86Instr_FpLdSt(
2811ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       True/*load*/, 4, dst,
2812ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       X86AMode_IR(0, hregX86_ESP())));
2813ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      add_to_esp(env, 4);
2814ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return dst;
2815ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2816ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2817ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_Binop && e->Iex.Binop.op == Iop_RoundF32toInt) {
2818ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HReg rf  = iselFltExpr(env, e->Iex.Binop.arg2);
2819ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HReg dst = newVRegF(env);
2820ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2821ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* rf now holds the value to be rounded.  The first thing to do
2822ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         is set the FPU's rounding mode accordingly. */
2823ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2824ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Set host rounding mode */
2825ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      set_FPU_rounding_mode( env, e->Iex.Binop.arg1 );
2826ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2827ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* grndint %rf, %dst */
2828ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env, X86Instr_FpUnary(Xfp_ROUND, rf, dst));
2829ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2830ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Restore default FPU rounding. */
2831ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      set_FPU_rounding_default( env );
2832ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2833ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return dst;
2834ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2835ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2836ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ppIRExpr(e);
2837ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vpanic("iselFltExpr_wrk");
2838ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2839ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2840ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2841ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------*/
2842ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- ISEL: Floating point expressions (64 bit)         ---*/
2843ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------*/
2844ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2845ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Compute a 64-bit floating point value into a register, the identity
2846ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   of which is returned.  As with iselIntExpr_R, the reg may be either
2847ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   real or virtual; in any case it must not be changed by subsequent
2848ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   code emitted by the caller.  */
2849ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2850ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* IEEE 754 formats.  From http://www.freesoft.org/CIE/RFC/1832/32.htm:
2851ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2852ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    Type                  S (1 bit)   E (11 bits)   F (52 bits)
2853ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    ----                  ---------   -----------   -----------
2854ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    signalling NaN        u           2047 (max)    .0uuuuu---u
2855ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                                    (with at least
2856ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                                     one 1 bit)
2857ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    quiet NaN             u           2047 (max)    .1uuuuu---u
2858ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2859ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    negative infinity     1           2047 (max)    .000000---0
2860ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2861ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    positive infinity     0           2047 (max)    .000000---0
2862ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2863ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    negative zero         1           0             .000000---0
2864ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2865ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    positive zero         0           0             .000000---0
2866ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
2867ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2868ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic HReg iselDblExpr ( ISelEnv* env, IRExpr* e )
2869ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2870ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   HReg r = iselDblExpr_wrk( env, e );
2871ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  if 0
2872ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vex_printf("\n"); ppIRExpr(e); vex_printf("\n");
2873ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  endif
2874ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(hregClass(r) == HRcFlt64);
2875ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(hregIsVirtual(r));
2876ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return r;
2877ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2878ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2879ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* DO NOT CALL THIS DIRECTLY */
2880ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic HReg iselDblExpr_wrk ( ISelEnv* env, IRExpr* e )
2881ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2882ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRType ty = typeOfIRExpr(env->type_env,e);
2883ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(e);
2884ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(ty == Ity_F64);
2885ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2886ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_RdTmp) {
2887ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return lookupIRTemp(env, e->Iex.RdTmp.tmp);
2888ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2889ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2890ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_Const) {
2891ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      union { UInt u32x2[2]; ULong u64; Double f64; } u;
2892ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HReg freg = newVRegF(env);
2893ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert(sizeof(u) == 8);
2894ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert(sizeof(u.u64) == 8);
2895ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert(sizeof(u.f64) == 8);
2896ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert(sizeof(u.u32x2) == 8);
2897ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2898ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (e->Iex.Const.con->tag == Ico_F64) {
2899ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         u.f64 = e->Iex.Const.con->Ico.F64;
2900ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2901ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      else if (e->Iex.Const.con->tag == Ico_F64i) {
2902ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         u.u64 = e->Iex.Const.con->Ico.F64i;
2903ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2904ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      else
2905ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vpanic("iselDblExpr(x86): const");
2906ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2907ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env, X86Instr_Push(X86RMI_Imm(u.u32x2[1])));
2908ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env, X86Instr_Push(X86RMI_Imm(u.u32x2[0])));
2909ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env, X86Instr_FpLdSt(True/*load*/, 8, freg,
2910ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                    X86AMode_IR(0, hregX86_ESP())));
2911ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      add_to_esp(env, 8);
2912ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return freg;
2913ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2914ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2915ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_Load && e->Iex.Load.end == Iend_LE) {
2916ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      X86AMode* am;
2917ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HReg res = newVRegF(env);
2918ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert(e->Iex.Load.ty == Ity_F64);
2919ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      am = iselIntExpr_AMode(env, e->Iex.Load.addr);
2920ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env, X86Instr_FpLdSt(True/*load*/, 8, res, am));
2921ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return res;
2922ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2923ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2924ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_Get) {
2925ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      X86AMode* am = X86AMode_IR( e->Iex.Get.offset,
2926ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                  hregX86_EBP() );
2927ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HReg res = newVRegF(env);
2928ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env, X86Instr_FpLdSt( True/*load*/, 8, res, am ));
2929ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return res;
2930ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2931ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2932ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_GetI) {
2933ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      X86AMode* am
2934ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         = genGuestArrayOffset(
2935ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              env, e->Iex.GetI.descr,
2936ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   e->Iex.GetI.ix, e->Iex.GetI.bias );
2937ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HReg res = newVRegF(env);
2938ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env, X86Instr_FpLdSt( True/*load*/, 8, res, am ));
2939ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return res;
2940ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2941ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2942ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_Triop) {
2943ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      X86FpOp fpop = Xfp_INVALID;
2944ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch (e->Iex.Triop.op) {
2945ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_AddF64:    fpop = Xfp_ADD; break;
2946ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_SubF64:    fpop = Xfp_SUB; break;
2947ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_MulF64:    fpop = Xfp_MUL; break;
2948ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_DivF64:    fpop = Xfp_DIV; break;
2949ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_ScaleF64:  fpop = Xfp_SCALE; break;
2950ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_Yl2xF64:   fpop = Xfp_YL2X; break;
2951ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_Yl2xp1F64: fpop = Xfp_YL2XP1; break;
2952ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_AtanF64:   fpop = Xfp_ATAN; break;
2953ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_PRemF64:   fpop = Xfp_PREM; break;
2954ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_PRem1F64:  fpop = Xfp_PREM1; break;
2955ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         default: break;
2956ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2957ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (fpop != Xfp_INVALID) {
2958ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg res  = newVRegF(env);
2959ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg srcL = iselDblExpr(env, e->Iex.Triop.arg2);
2960ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg srcR = iselDblExpr(env, e->Iex.Triop.arg3);
2961ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* XXXROUNDINGFIXME */
2962ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* set roundingmode here */
2963ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, X86Instr_FpBinary(fpop,srcL,srcR,res));
2964ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 if (fpop != Xfp_ADD && fpop != Xfp_SUB
2965ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	     && fpop != Xfp_MUL && fpop != Xfp_DIV)
2966ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            roundToF64(env, res);
2967ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return res;
2968ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2969ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2970ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2971ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_Binop && e->Iex.Binop.op == Iop_RoundF64toInt) {
2972ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HReg rf  = iselDblExpr(env, e->Iex.Binop.arg2);
2973ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HReg dst = newVRegF(env);
2974ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2975ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* rf now holds the value to be rounded.  The first thing to do
2976ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         is set the FPU's rounding mode accordingly. */
2977ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2978ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Set host rounding mode */
2979ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      set_FPU_rounding_mode( env, e->Iex.Binop.arg1 );
2980ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2981ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* grndint %rf, %dst */
2982ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env, X86Instr_FpUnary(Xfp_ROUND, rf, dst));
2983ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2984ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Restore default FPU rounding. */
2985ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      set_FPU_rounding_default( env );
2986ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2987ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return dst;
2988ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2989ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2990ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_Binop && e->Iex.Binop.op == Iop_I64StoF64) {
2991ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HReg dst = newVRegF(env);
2992ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HReg rHi,rLo;
2993ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      iselInt64Expr( &rHi, &rLo, env, e->Iex.Binop.arg2);
2994ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env, X86Instr_Push(X86RMI_Reg(rHi)));
2995ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env, X86Instr_Push(X86RMI_Reg(rLo)));
2996ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2997ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Set host rounding mode */
2998ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      set_FPU_rounding_mode( env, e->Iex.Binop.arg1 );
2999ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3000ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env, X86Instr_FpLdStI(
3001ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       True/*load*/, 8, dst,
3002ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       X86AMode_IR(0, hregX86_ESP())));
3003ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3004ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Restore default FPU rounding. */
3005ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      set_FPU_rounding_default( env );
3006ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3007ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      add_to_esp(env, 8);
3008ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return dst;
3009ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3010ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3011ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_Binop) {
3012ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      X86FpOp fpop = Xfp_INVALID;
3013ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch (e->Iex.Binop.op) {
3014ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_SinF64:  fpop = Xfp_SIN; break;
3015ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_CosF64:  fpop = Xfp_COS; break;
3016ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_TanF64:  fpop = Xfp_TAN; break;
3017ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_2xm1F64: fpop = Xfp_2XM1; break;
3018ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_SqrtF64: fpop = Xfp_SQRT; break;
3019ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         default: break;
3020ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3021ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (fpop != Xfp_INVALID) {
3022ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg res = newVRegF(env);
3023ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg src = iselDblExpr(env, e->Iex.Binop.arg2);
3024ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* XXXROUNDINGFIXME */
3025ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* set roundingmode here */
3026ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, X86Instr_FpUnary(fpop,src,res));
3027ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 if (fpop != Xfp_SQRT
3028ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             && fpop != Xfp_NEG && fpop != Xfp_ABS)
3029ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            roundToF64(env, res);
3030ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return res;
3031ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3032ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3033ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3034ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_Unop) {
3035ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      X86FpOp fpop = Xfp_INVALID;
3036ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch (e->Iex.Unop.op) {
3037ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_NegF64:  fpop = Xfp_NEG; break;
3038ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_AbsF64:  fpop = Xfp_ABS; break;
3039ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         default: break;
3040ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3041ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (fpop != Xfp_INVALID) {
3042ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg res = newVRegF(env);
3043ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg src = iselDblExpr(env, e->Iex.Unop.arg);
3044ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, X86Instr_FpUnary(fpop,src,res));
3045ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 if (fpop != Xfp_NEG && fpop != Xfp_ABS)
3046ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            roundToF64(env, res);
3047ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return res;
3048ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3049ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3050ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3051ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_Unop) {
3052ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch (e->Iex.Unop.op) {
3053ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_I32StoF64: {
3054ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg dst = newVRegF(env);
3055ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg ri  = iselIntExpr_R(env, e->Iex.Unop.arg);
3056ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, X86Instr_Push(X86RMI_Reg(ri)));
3057ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            set_FPU_rounding_default(env);
3058ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, X86Instr_FpLdStI(
3059ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             True/*load*/, 4, dst,
3060ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             X86AMode_IR(0, hregX86_ESP())));
3061ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    add_to_esp(env, 4);
3062ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return dst;
3063ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
3064ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_ReinterpI64asF64: {
3065ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* Given an I64, produce an IEEE754 double with the same
3066ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               bit pattern. */
3067ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg dst = newVRegF(env);
3068ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg rHi, rLo;
3069ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    iselInt64Expr( &rHi, &rLo, env, e->Iex.Unop.arg);
3070ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* paranoia */
3071ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            set_FPU_rounding_default(env);
3072ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, X86Instr_Push(X86RMI_Reg(rHi)));
3073ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, X86Instr_Push(X86RMI_Reg(rLo)));
3074ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, X86Instr_FpLdSt(
3075ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             True/*load*/, 8, dst,
3076ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             X86AMode_IR(0, hregX86_ESP())));
3077ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    add_to_esp(env, 8);
3078ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return dst;
3079ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 }
3080ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_F32toF64: {
3081ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* this is a no-op */
3082ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg res = iselFltExpr(env, e->Iex.Unop.arg);
3083ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return res;
3084ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 }
3085ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         default:
3086ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
3087ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3088ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3089ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3090ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* --------- MULTIPLEX --------- */
3091ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_Mux0X) {
3092ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     if (ty == Ity_F64
3093ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         && typeOfIRExpr(env->type_env,e->Iex.Mux0X.cond) == Ity_I8) {
3094ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        X86RM* r8 = iselIntExpr_RM(env, e->Iex.Mux0X.cond);
3095ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        HReg rX  = iselDblExpr(env, e->Iex.Mux0X.exprX);
3096ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        HReg r0  = iselDblExpr(env, e->Iex.Mux0X.expr0);
3097ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        HReg dst = newVRegF(env);
3098ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        addInstr(env, X86Instr_FpUnary(Xfp_MOV,rX,dst));
3099ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        addInstr(env, X86Instr_Test32(0xFF, r8));
3100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        addInstr(env, X86Instr_FpCMov(Xcc_Z,r0,dst));
3101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        return dst;
3102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ppIRExpr(e);
3106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vpanic("iselDblExpr_wrk");
3107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------*/
3111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- ISEL: SIMD (Vector) expressions, 128 bit.         ---*/
3112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------*/
3113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic HReg iselVecExpr ( ISelEnv* env, IRExpr* e )
3115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
3116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   HReg r = iselVecExpr_wrk( env, e );
3117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  if 0
3118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vex_printf("\n"); ppIRExpr(e); vex_printf("\n");
3119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  endif
3120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(hregClass(r) == HRcVec128);
3121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(hregIsVirtual(r));
3122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return r;
3123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* DO NOT CALL THIS DIRECTLY */
3127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic HReg iselVecExpr_wrk ( ISelEnv* env, IRExpr* e )
3128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
3129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  define REQUIRE_SSE1                                    \
3131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      do { if (env->hwcaps == 0/*baseline, no sse*/)      \
3132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              goto vec_fail;                              \
3133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } while (0)
3134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  define REQUIRE_SSE2                                    \
3136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      do { if (0 == (env->hwcaps & VEX_HWCAPS_X86_SSE2))  \
3137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              goto vec_fail;                              \
3138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } while (0)
3139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  define SSE2_OR_ABOVE                                   \
3141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       (env->hwcaps & VEX_HWCAPS_X86_SSE2)
3142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3143b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   HWord     fn = 0; /* address of helper fn, if required */
3144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   MatchInfo mi;
3145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Bool      arg1isEReg = False;
3146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   X86SseOp  op = Xsse_INVALID;
3147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRType    ty = typeOfIRExpr(env->type_env,e);
3148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(e);
3149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(ty == Ity_V128);
3150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   REQUIRE_SSE1;
3152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_RdTmp) {
3154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return lookupIRTemp(env, e->Iex.RdTmp.tmp);
3155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_Get) {
3158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HReg dst = newVRegV(env);
3159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env, X86Instr_SseLdSt(
3160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       True/*load*/,
3161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       dst,
3162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       X86AMode_IR(e->Iex.Get.offset, hregX86_EBP())
3163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    )
3164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              );
3165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return dst;
3166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_Load && e->Iex.Load.end == Iend_LE) {
3169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HReg      dst = newVRegV(env);
3170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      X86AMode* am  = iselIntExpr_AMode(env, e->Iex.Load.addr);
3171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env, X86Instr_SseLdSt( True/*load*/, dst, am ));
3172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return dst;
3173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_Const) {
3176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HReg dst = newVRegV(env);
3177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert(e->Iex.Const.con->tag == Ico_V128);
3178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env, X86Instr_SseConst(e->Iex.Const.con->Ico.V128, dst));
3179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return dst;
3180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_Unop) {
3183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (SSE2_OR_ABOVE) {
3185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* 64UtoV128(LDle:I64(addr)) */
3186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DECLARE_PATTERN(p_zwiden_load64);
3187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DEFINE_PATTERN(p_zwiden_load64,
3188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     unop(Iop_64UtoV128,
3189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          IRExpr_Load(Iend_LE,Ity_I64,bind(0))));
3190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (matchIRExpr(&mi, p_zwiden_load64, e)) {
3191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         X86AMode* am = iselIntExpr_AMode(env, mi.bindee[0]);
3192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg dst = newVRegV(env);
3193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, X86Instr_SseLdzLO(8, dst, am));
3194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return dst;
3195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (e->Iex.Unop.op) {
3199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_NotV128: {
3201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg arg = iselVecExpr(env, e->Iex.Unop.arg);
3202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return do_sse_Not128(env, arg);
3203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpNEZ64x2: {
3206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* We can use SSE2 instructions for this. */
3207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Ideally, we want to do a 64Ix2 comparison against zero of
3208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            the operand.  Problem is no such insn exists.  Solution
3209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            therefore is to do a 32Ix4 comparison instead, and bitwise-
3210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            negate (NOT) the result.  Let a,b,c,d be 32-bit lanes, and
3211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            let the not'd result of this initial comparison be a:b:c:d.
3212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            What we need to compute is (a|b):(a|b):(c|d):(c|d).  So, use
3213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            pshufd to create a value b:a:d:c, and OR that with a:b:c:d,
3214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            giving the required result.
3215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            The required selection sequence is 2,3,0,1, which
3217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            according to Intel's documentation means the pshufd
3218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            literal value is 0xB1, that is,
3219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            (2 << 6) | (3 << 4) | (0 << 2) | (1 << 0)
3220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         */
3221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg arg  = iselVecExpr(env, e->Iex.Unop.arg);
3222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg tmp  = newVRegV(env);
3223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg dst  = newVRegV(env);
3224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         REQUIRE_SSE2;
3225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, X86Instr_SseReRg(Xsse_XOR, tmp, tmp));
3226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, X86Instr_SseReRg(Xsse_CMPEQ32, arg, tmp));
3227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         tmp = do_sse_Not128(env, tmp);
3228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, X86Instr_SseShuf(0xB1, tmp, dst));
3229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, X86Instr_SseReRg(Xsse_OR, tmp, dst));
3230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return dst;
3231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpNEZ32x4: {
3234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Sigh, we have to generate lousy code since this has to
3235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            work on SSE1 hosts */
3236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* basically, the idea is: for each lane:
3237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               movl lane, %r ; negl %r   (now CF = lane==0 ? 0 : 1)
3238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               sbbl %r, %r               (now %r = 1Sto32(CF))
3239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               movl %r, lane
3240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         */
3241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         Int       i;
3242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         X86AMode* am;
3243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         X86AMode* esp0 = X86AMode_IR(0, hregX86_ESP());
3244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg      arg  = iselVecExpr(env, e->Iex.Unop.arg);
3245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg      dst  = newVRegV(env);
3246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg      r32  = newVRegI(env);
3247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         sub_from_esp(env, 16);
3248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, X86Instr_SseLdSt(False/*store*/, arg, esp0));
3249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         for (i = 0; i < 4; i++) {
3250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            am = X86AMode_IR(i*4, hregX86_ESP());
3251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, X86Instr_Alu32R(Xalu_MOV, X86RMI_Mem(am), r32));
3252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, X86Instr_Unary32(Xun_NEG, r32));
3253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, X86Instr_Alu32R(Xalu_SBB, X86RMI_Reg(r32), r32));
3254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, X86Instr_Alu32M(Xalu_MOV, X86RI_Reg(r32), am));
3255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
3256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, X86Instr_SseLdSt(True/*load*/, dst, esp0));
3257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         add_to_esp(env, 16);
3258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return dst;
3259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpNEZ8x16:
3262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpNEZ16x8: {
3263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* We can use SSE2 instructions for this. */
3264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg arg;
3265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg vec0 = newVRegV(env);
3266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg vec1 = newVRegV(env);
3267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg dst  = newVRegV(env);
3268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         X86SseOp cmpOp
3269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            = e->Iex.Unop.op==Iop_CmpNEZ16x8 ? Xsse_CMPEQ16
3270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                             : Xsse_CMPEQ8;
3271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         REQUIRE_SSE2;
3272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, X86Instr_SseReRg(Xsse_XOR, vec0, vec0));
3273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, mk_vMOVsd_RR(vec0, vec1));
3274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, X86Instr_Sse32Fx4(Xsse_CMPEQF, vec1, vec1));
3275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* defer arg computation to here so as to give CMPEQF as long
3276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            as possible to complete */
3277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         arg = iselVecExpr(env, e->Iex.Unop.arg);
3278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* vec0 is all 0s; vec1 is all 1s */
3279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, mk_vMOVsd_RR(arg, dst));
3280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* 16x8 or 8x16 comparison == */
3281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, X86Instr_SseReRg(cmpOp, vec0, dst));
3282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* invert result */
3283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, X86Instr_SseReRg(Xsse_XOR, vec1, dst));
3284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return dst;
3285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Recip32Fx4: op = Xsse_RCPF;   goto do_32Fx4_unary;
3288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_RSqrt32Fx4: op = Xsse_RSQRTF; goto do_32Fx4_unary;
3289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Sqrt32Fx4:  op = Xsse_SQRTF;  goto do_32Fx4_unary;
3290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      do_32Fx4_unary:
3291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      {
3292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg arg = iselVecExpr(env, e->Iex.Unop.arg);
3293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg dst = newVRegV(env);
3294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, X86Instr_Sse32Fx4(op, arg, dst));
3295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return dst;
3296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Recip64Fx2: op = Xsse_RCPF;   goto do_64Fx2_unary;
3299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_RSqrt64Fx2: op = Xsse_RSQRTF; goto do_64Fx2_unary;
3300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Sqrt64Fx2:  op = Xsse_SQRTF;  goto do_64Fx2_unary;
3301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      do_64Fx2_unary:
3302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      {
3303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg arg = iselVecExpr(env, e->Iex.Unop.arg);
3304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg dst = newVRegV(env);
3305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         REQUIRE_SSE2;
3306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, X86Instr_Sse64Fx2(op, arg, dst));
3307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return dst;
3308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Recip32F0x4: op = Xsse_RCPF;   goto do_32F0x4_unary;
3311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_RSqrt32F0x4: op = Xsse_RSQRTF; goto do_32F0x4_unary;
3312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Sqrt32F0x4:  op = Xsse_SQRTF;  goto do_32F0x4_unary;
3313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      do_32F0x4_unary:
3314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      {
3315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* A bit subtle.  We have to copy the arg to the result
3316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            register first, because actually doing the SSE scalar insn
3317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            leaves the upper 3/4 of the destination register
3318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            unchanged.  Whereas the required semantics of these
3319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            primops is that the upper 3/4 is simply copied in from the
3320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            argument. */
3321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg arg = iselVecExpr(env, e->Iex.Unop.arg);
3322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg dst = newVRegV(env);
3323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, mk_vMOVsd_RR(arg, dst));
3324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, X86Instr_Sse32FLo(op, arg, dst));
3325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return dst;
3326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Recip64F0x2: op = Xsse_RCPF;   goto do_64F0x2_unary;
3329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_RSqrt64F0x2: op = Xsse_RSQRTF; goto do_64F0x2_unary;
3330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Sqrt64F0x2:  op = Xsse_SQRTF;  goto do_64F0x2_unary;
3331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      do_64F0x2_unary:
3332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      {
3333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* A bit subtle.  We have to copy the arg to the result
3334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            register first, because actually doing the SSE scalar insn
3335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            leaves the upper half of the destination register
3336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            unchanged.  Whereas the required semantics of these
3337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            primops is that the upper half is simply copied in from the
3338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            argument. */
3339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg arg = iselVecExpr(env, e->Iex.Unop.arg);
3340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg dst = newVRegV(env);
3341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         REQUIRE_SSE2;
3342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, mk_vMOVsd_RR(arg, dst));
3343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, X86Instr_Sse64FLo(op, arg, dst));
3344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return dst;
3345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_32UtoV128: {
3348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg      dst  = newVRegV(env);
3349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         X86AMode* esp0 = X86AMode_IR(0, hregX86_ESP());
3350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         X86RMI*   rmi  = iselIntExpr_RMI(env, e->Iex.Unop.arg);
3351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, X86Instr_Push(rmi));
3352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 addInstr(env, X86Instr_SseLdzLO(4, dst, esp0));
3353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         add_to_esp(env, 4);
3354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return dst;
3355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_64UtoV128: {
3358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg      rHi, rLo;
3359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg      dst  = newVRegV(env);
3360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         X86AMode* esp0 = X86AMode_IR(0, hregX86_ESP());
3361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         iselInt64Expr(&rHi, &rLo, env, e->Iex.Unop.arg);
3362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, X86Instr_Push(X86RMI_Reg(rHi)));
3363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, X86Instr_Push(X86RMI_Reg(rLo)));
3364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 addInstr(env, X86Instr_SseLdzLO(8, dst, esp0));
3365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         add_to_esp(env, 8);
3366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return dst;
3367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
3370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
3371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } /* switch (e->Iex.Unop.op) */
3372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } /* if (e->tag == Iex_Unop) */
3373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_Binop) {
3375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (e->Iex.Binop.op) {
3376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_SetV128lo32: {
3378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg dst = newVRegV(env);
3379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg srcV = iselVecExpr(env, e->Iex.Binop.arg1);
3380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg srcI = iselIntExpr_R(env, e->Iex.Binop.arg2);
3381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         X86AMode* esp0 = X86AMode_IR(0, hregX86_ESP());
3382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         sub_from_esp(env, 16);
3383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, X86Instr_SseLdSt(False/*store*/, srcV, esp0));
3384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, X86Instr_Alu32M(Xalu_MOV, X86RI_Reg(srcI), esp0));
3385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, X86Instr_SseLdSt(True/*load*/, dst, esp0));
3386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         add_to_esp(env, 16);
3387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return dst;
3388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_SetV128lo64: {
3391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg dst = newVRegV(env);
3392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg srcV = iselVecExpr(env, e->Iex.Binop.arg1);
3393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg srcIhi, srcIlo;
3394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         X86AMode* esp0 = X86AMode_IR(0, hregX86_ESP());
3395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         X86AMode* esp4 = advance4(esp0);
3396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         iselInt64Expr(&srcIhi, &srcIlo, env, e->Iex.Binop.arg2);
3397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         sub_from_esp(env, 16);
3398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, X86Instr_SseLdSt(False/*store*/, srcV, esp0));
3399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, X86Instr_Alu32M(Xalu_MOV, X86RI_Reg(srcIlo), esp0));
3400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, X86Instr_Alu32M(Xalu_MOV, X86RI_Reg(srcIhi), esp4));
3401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, X86Instr_SseLdSt(True/*load*/, dst, esp0));
3402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         add_to_esp(env, 16);
3403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return dst;
3404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_64HLtoV128: {
3407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg r3, r2, r1, r0;
3408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         X86AMode* esp0  = X86AMode_IR(0, hregX86_ESP());
3409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         X86AMode* esp4  = advance4(esp0);
3410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         X86AMode* esp8  = advance4(esp4);
3411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         X86AMode* esp12 = advance4(esp8);
3412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg dst = newVRegV(env);
3413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 /* do this via the stack (easy, convenient, etc) */
3414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         sub_from_esp(env, 16);
3415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Do the less significant 64 bits */
3416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         iselInt64Expr(&r1, &r0, env, e->Iex.Binop.arg2);
3417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, X86Instr_Alu32M(Xalu_MOV, X86RI_Reg(r0), esp0));
3418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, X86Instr_Alu32M(Xalu_MOV, X86RI_Reg(r1), esp4));
3419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Do the more significant 64 bits */
3420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         iselInt64Expr(&r3, &r2, env, e->Iex.Binop.arg1);
3421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, X86Instr_Alu32M(Xalu_MOV, X86RI_Reg(r2), esp8));
3422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, X86Instr_Alu32M(Xalu_MOV, X86RI_Reg(r3), esp12));
3423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 /* Fetch result back from stack. */
3424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, X86Instr_SseLdSt(True/*load*/, dst, esp0));
3425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         add_to_esp(env, 16);
3426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return dst;
3427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpEQ32Fx4: op = Xsse_CMPEQF; goto do_32Fx4;
3430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpLT32Fx4: op = Xsse_CMPLTF; goto do_32Fx4;
3431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpLE32Fx4: op = Xsse_CMPLEF; goto do_32Fx4;
3432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpUN32Fx4: op = Xsse_CMPUNF; goto do_32Fx4;
3433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Add32Fx4:   op = Xsse_ADDF;   goto do_32Fx4;
3434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Div32Fx4:   op = Xsse_DIVF;   goto do_32Fx4;
3435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Max32Fx4:   op = Xsse_MAXF;   goto do_32Fx4;
3436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Min32Fx4:   op = Xsse_MINF;   goto do_32Fx4;
3437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Mul32Fx4:   op = Xsse_MULF;   goto do_32Fx4;
3438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Sub32Fx4:   op = Xsse_SUBF;   goto do_32Fx4;
3439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      do_32Fx4:
3440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      {
3441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg argL = iselVecExpr(env, e->Iex.Binop.arg1);
3442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg argR = iselVecExpr(env, e->Iex.Binop.arg2);
3443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg dst = newVRegV(env);
3444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, mk_vMOVsd_RR(argL, dst));
3445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, X86Instr_Sse32Fx4(op, argR, dst));
3446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return dst;
3447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpEQ64Fx2: op = Xsse_CMPEQF; goto do_64Fx2;
3450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpLT64Fx2: op = Xsse_CMPLTF; goto do_64Fx2;
3451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpLE64Fx2: op = Xsse_CMPLEF; goto do_64Fx2;
3452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpUN64Fx2: op = Xsse_CMPUNF; goto do_64Fx2;
3453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Add64Fx2:   op = Xsse_ADDF;   goto do_64Fx2;
3454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Div64Fx2:   op = Xsse_DIVF;   goto do_64Fx2;
3455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Max64Fx2:   op = Xsse_MAXF;   goto do_64Fx2;
3456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Min64Fx2:   op = Xsse_MINF;   goto do_64Fx2;
3457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Mul64Fx2:   op = Xsse_MULF;   goto do_64Fx2;
3458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Sub64Fx2:   op = Xsse_SUBF;   goto do_64Fx2;
3459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      do_64Fx2:
3460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      {
3461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg argL = iselVecExpr(env, e->Iex.Binop.arg1);
3462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg argR = iselVecExpr(env, e->Iex.Binop.arg2);
3463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg dst = newVRegV(env);
3464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         REQUIRE_SSE2;
3465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, mk_vMOVsd_RR(argL, dst));
3466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, X86Instr_Sse64Fx2(op, argR, dst));
3467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return dst;
3468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpEQ32F0x4: op = Xsse_CMPEQF; goto do_32F0x4;
3471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpLT32F0x4: op = Xsse_CMPLTF; goto do_32F0x4;
3472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpLE32F0x4: op = Xsse_CMPLEF; goto do_32F0x4;
3473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpUN32F0x4: op = Xsse_CMPUNF; goto do_32F0x4;
3474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Add32F0x4:   op = Xsse_ADDF;   goto do_32F0x4;
3475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Div32F0x4:   op = Xsse_DIVF;   goto do_32F0x4;
3476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Max32F0x4:   op = Xsse_MAXF;   goto do_32F0x4;
3477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Min32F0x4:   op = Xsse_MINF;   goto do_32F0x4;
3478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Mul32F0x4:   op = Xsse_MULF;   goto do_32F0x4;
3479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Sub32F0x4:   op = Xsse_SUBF;   goto do_32F0x4;
3480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      do_32F0x4: {
3481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg argL = iselVecExpr(env, e->Iex.Binop.arg1);
3482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg argR = iselVecExpr(env, e->Iex.Binop.arg2);
3483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg dst = newVRegV(env);
3484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, mk_vMOVsd_RR(argL, dst));
3485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, X86Instr_Sse32FLo(op, argR, dst));
3486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return dst;
3487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpEQ64F0x2: op = Xsse_CMPEQF; goto do_64F0x2;
3490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpLT64F0x2: op = Xsse_CMPLTF; goto do_64F0x2;
3491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpLE64F0x2: op = Xsse_CMPLEF; goto do_64F0x2;
3492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpUN64F0x2: op = Xsse_CMPUNF; goto do_64F0x2;
3493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Add64F0x2:   op = Xsse_ADDF;   goto do_64F0x2;
3494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Div64F0x2:   op = Xsse_DIVF;   goto do_64F0x2;
3495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Max64F0x2:   op = Xsse_MAXF;   goto do_64F0x2;
3496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Min64F0x2:   op = Xsse_MINF;   goto do_64F0x2;
3497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Mul64F0x2:   op = Xsse_MULF;   goto do_64F0x2;
3498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Sub64F0x2:   op = Xsse_SUBF;   goto do_64F0x2;
3499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      do_64F0x2: {
3500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg argL = iselVecExpr(env, e->Iex.Binop.arg1);
3501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg argR = iselVecExpr(env, e->Iex.Binop.arg2);
3502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg dst = newVRegV(env);
3503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         REQUIRE_SSE2;
3504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, mk_vMOVsd_RR(argL, dst));
3505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, X86Instr_Sse64FLo(op, argR, dst));
3506ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return dst;
3507ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3508ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3509b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_QNarrowBin32Sto16Sx8:
3510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         op = Xsse_PACKSSD; arg1isEReg = True; goto do_SseReRg;
3511b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_QNarrowBin16Sto8Sx16:
3512ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         op = Xsse_PACKSSW; arg1isEReg = True; goto do_SseReRg;
3513b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_QNarrowBin16Sto8Ux16:
3514ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         op = Xsse_PACKUSW; arg1isEReg = True; goto do_SseReRg;
3515ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3516ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_InterleaveHI8x16:
3517ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         op = Xsse_UNPCKHB; arg1isEReg = True; goto do_SseReRg;
3518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_InterleaveHI16x8:
3519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         op = Xsse_UNPCKHW; arg1isEReg = True; goto do_SseReRg;
3520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_InterleaveHI32x4:
3521ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         op = Xsse_UNPCKHD; arg1isEReg = True; goto do_SseReRg;
3522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_InterleaveHI64x2:
3523ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         op = Xsse_UNPCKHQ; arg1isEReg = True; goto do_SseReRg;
3524ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3525ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_InterleaveLO8x16:
3526ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         op = Xsse_UNPCKLB; arg1isEReg = True; goto do_SseReRg;
3527ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_InterleaveLO16x8:
3528ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         op = Xsse_UNPCKLW; arg1isEReg = True; goto do_SseReRg;
3529ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_InterleaveLO32x4:
3530ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         op = Xsse_UNPCKLD; arg1isEReg = True; goto do_SseReRg;
3531ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_InterleaveLO64x2:
3532ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         op = Xsse_UNPCKLQ; arg1isEReg = True; goto do_SseReRg;
3533ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3534ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_AndV128:    op = Xsse_AND;      goto do_SseReRg;
3535ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_OrV128:     op = Xsse_OR;       goto do_SseReRg;
3536ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_XorV128:    op = Xsse_XOR;      goto do_SseReRg;
3537ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Add8x16:    op = Xsse_ADD8;     goto do_SseReRg;
3538ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Add16x8:    op = Xsse_ADD16;    goto do_SseReRg;
3539ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Add32x4:    op = Xsse_ADD32;    goto do_SseReRg;
3540ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Add64x2:    op = Xsse_ADD64;    goto do_SseReRg;
3541ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QAdd8Sx16:  op = Xsse_QADD8S;   goto do_SseReRg;
3542ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QAdd16Sx8:  op = Xsse_QADD16S;  goto do_SseReRg;
3543ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QAdd8Ux16:  op = Xsse_QADD8U;   goto do_SseReRg;
3544ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QAdd16Ux8:  op = Xsse_QADD16U;  goto do_SseReRg;
3545ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Avg8Ux16:   op = Xsse_AVG8U;    goto do_SseReRg;
3546ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Avg16Ux8:   op = Xsse_AVG16U;   goto do_SseReRg;
3547ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpEQ8x16:  op = Xsse_CMPEQ8;   goto do_SseReRg;
3548ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpEQ16x8:  op = Xsse_CMPEQ16;  goto do_SseReRg;
3549ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpEQ32x4:  op = Xsse_CMPEQ32;  goto do_SseReRg;
3550ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpGT8Sx16: op = Xsse_CMPGT8S;  goto do_SseReRg;
3551ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpGT16Sx8: op = Xsse_CMPGT16S; goto do_SseReRg;
3552ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpGT32Sx4: op = Xsse_CMPGT32S; goto do_SseReRg;
3553ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Max16Sx8:   op = Xsse_MAX16S;   goto do_SseReRg;
3554ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Max8Ux16:   op = Xsse_MAX8U;    goto do_SseReRg;
3555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Min16Sx8:   op = Xsse_MIN16S;   goto do_SseReRg;
3556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Min8Ux16:   op = Xsse_MIN8U;    goto do_SseReRg;
3557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_MulHi16Ux8: op = Xsse_MULHI16U; goto do_SseReRg;
3558ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_MulHi16Sx8: op = Xsse_MULHI16S; goto do_SseReRg;
3559ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Mul16x8:    op = Xsse_MUL16;    goto do_SseReRg;
3560ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Sub8x16:    op = Xsse_SUB8;     goto do_SseReRg;
3561ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Sub16x8:    op = Xsse_SUB16;    goto do_SseReRg;
3562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Sub32x4:    op = Xsse_SUB32;    goto do_SseReRg;
3563ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Sub64x2:    op = Xsse_SUB64;    goto do_SseReRg;
3564ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QSub8Sx16:  op = Xsse_QSUB8S;   goto do_SseReRg;
3565ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QSub16Sx8:  op = Xsse_QSUB16S;  goto do_SseReRg;
3566ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QSub8Ux16:  op = Xsse_QSUB8U;   goto do_SseReRg;
3567ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QSub16Ux8:  op = Xsse_QSUB16U;  goto do_SseReRg;
3568ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      do_SseReRg: {
3569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg arg1 = iselVecExpr(env, e->Iex.Binop.arg1);
3570ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg arg2 = iselVecExpr(env, e->Iex.Binop.arg2);
3571ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg dst = newVRegV(env);
3572ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (op != Xsse_OR && op != Xsse_AND && op != Xsse_XOR)
3573ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            REQUIRE_SSE2;
3574ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (arg1isEReg) {
3575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, mk_vMOVsd_RR(arg2, dst));
3576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, X86Instr_SseReRg(op, arg1, dst));
3577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
3578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, mk_vMOVsd_RR(arg1, dst));
3579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, X86Instr_SseReRg(op, arg2, dst));
3580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
3581ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return dst;
3582ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3584ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_ShlN16x8: op = Xsse_SHL16; goto do_SseShift;
3585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_ShlN32x4: op = Xsse_SHL32; goto do_SseShift;
3586ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_ShlN64x2: op = Xsse_SHL64; goto do_SseShift;
3587ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_SarN16x8: op = Xsse_SAR16; goto do_SseShift;
3588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_SarN32x4: op = Xsse_SAR32; goto do_SseShift;
3589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_ShrN16x8: op = Xsse_SHR16; goto do_SseShift;
3590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_ShrN32x4: op = Xsse_SHR32; goto do_SseShift;
3591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_ShrN64x2: op = Xsse_SHR64; goto do_SseShift;
3592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      do_SseShift: {
3593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg      greg = iselVecExpr(env, e->Iex.Binop.arg1);
3594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         X86RMI*   rmi  = iselIntExpr_RMI(env, e->Iex.Binop.arg2);
3595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         X86AMode* esp0 = X86AMode_IR(0, hregX86_ESP());
3596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg      ereg = newVRegV(env);
3597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg      dst  = newVRegV(env);
3598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         REQUIRE_SSE2;
3599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, X86Instr_Push(X86RMI_Imm(0)));
3600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, X86Instr_Push(X86RMI_Imm(0)));
3601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, X86Instr_Push(X86RMI_Imm(0)));
3602ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, X86Instr_Push(rmi));
3603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, X86Instr_SseLdSt(True/*load*/, ereg, esp0));
3604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 addInstr(env, mk_vMOVsd_RR(greg, dst));
3605ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, X86Instr_SseReRg(op, ereg, dst));
3606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         add_to_esp(env, 16);
3607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return dst;
3608ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3609ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3610b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_NarrowBin32to16x8:
3611b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         fn = (HWord)h_generic_calc_NarrowBin32to16x8;
3612b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         goto do_SseAssistedBinary;
3613b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_NarrowBin16to8x16:
3614b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         fn = (HWord)h_generic_calc_NarrowBin16to8x16;
3615b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         goto do_SseAssistedBinary;
3616b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      do_SseAssistedBinary: {
3617b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         /* As with the amd64 case (where this is copied from) we
3618b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            generate pretty bad code. */
3619b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         vassert(fn != 0);
3620b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         HReg dst = newVRegV(env);
3621b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         HReg argL = iselVecExpr(env, e->Iex.Binop.arg1);
3622b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         HReg argR = iselVecExpr(env, e->Iex.Binop.arg2);
3623b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         HReg argp = newVRegI(env);
3624b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         /* subl $112, %esp         -- make a space */
3625b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         sub_from_esp(env, 112);
3626b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         /* leal 48(%esp), %r_argp  -- point into it */
3627b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         addInstr(env, X86Instr_Lea32(X86AMode_IR(48, hregX86_ESP()),
3628b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                      argp));
3629b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         /* andl $-16, %r_argp      -- 16-align the pointer */
3630b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         addInstr(env, X86Instr_Alu32R(Xalu_AND,
3631b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                       X86RMI_Imm( ~(UInt)15 ),
3632b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                       argp));
3633b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         /* Prepare 3 arg regs:
3634b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            leal  0(%r_argp), %eax
3635b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            leal 16(%r_argp), %edx
3636b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            leal 32(%r_argp), %ecx
3637b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         */
3638b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         addInstr(env, X86Instr_Lea32(X86AMode_IR(0, argp),
3639b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                      hregX86_EAX()));
3640b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         addInstr(env, X86Instr_Lea32(X86AMode_IR(16, argp),
3641b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                      hregX86_EDX()));
3642b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         addInstr(env, X86Instr_Lea32(X86AMode_IR(32, argp),
3643b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                      hregX86_ECX()));
3644b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         /* Store the two args, at (%edx) and (%ecx):
3645b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            movupd  %argL, 0(%edx)
3646b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            movupd  %argR, 0(%ecx)
3647b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         */
3648b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         addInstr(env, X86Instr_SseLdSt(False/*!isLoad*/, argL,
3649b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                        X86AMode_IR(0, hregX86_EDX())));
3650b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         addInstr(env, X86Instr_SseLdSt(False/*!isLoad*/, argR,
3651b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                        X86AMode_IR(0, hregX86_ECX())));
3652b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         /* call the helper */
3653b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         addInstr(env, X86Instr_Call( Xcc_ALWAYS, (Addr32)fn, 3 ));
3654b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         /* fetch the result from memory, using %r_argp, which the
3655b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            register allocator will keep alive across the call. */
3656b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         addInstr(env, X86Instr_SseLdSt(True/*isLoad*/, dst,
3657b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                        X86AMode_IR(0, argp)));
3658b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         /* and finally, clear the space */
3659b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         add_to_esp(env, 112);
3660b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         return dst;
3661b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      }
3662b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
3663ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
3664ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
3665ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } /* switch (e->Iex.Binop.op) */
3666ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } /* if (e->tag == Iex_Binop) */
3667ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3668ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_Mux0X) {
3669ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      X86RM* r8 = iselIntExpr_RM(env, e->Iex.Mux0X.cond);
3670ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HReg rX  = iselVecExpr(env, e->Iex.Mux0X.exprX);
3671ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HReg r0  = iselVecExpr(env, e->Iex.Mux0X.expr0);
3672ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HReg dst = newVRegV(env);
3673ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env, mk_vMOVsd_RR(rX,dst));
3674ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env, X86Instr_Test32(0xFF, r8));
3675ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env, X86Instr_SseCMov(Xcc_Z,r0,dst));
3676ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return dst;
3677ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3678ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3679ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vec_fail:
3680ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vex_printf("iselVecExpr (hwcaps = %s): can't reduce\n",
3681ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              LibVEX_ppVexHwCaps(VexArchX86,env->hwcaps));
3682ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ppIRExpr(e);
3683ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vpanic("iselVecExpr_wrk");
3684ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3685ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  undef REQUIRE_SSE1
3686ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  undef REQUIRE_SSE2
3687ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  undef SSE2_OR_ABOVE
3688ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3689ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3690ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3691ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------*/
3692ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- ISEL: Statements                                  ---*/
3693ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------*/
3694ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3695ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void iselStmt ( ISelEnv* env, IRStmt* stmt )
3696ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
3697ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (vex_traceflags & VEX_TRACE_VCODE) {
3698ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vex_printf("\n-- ");
3699ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ppIRStmt(stmt);
3700ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vex_printf("\n");
3701ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3702ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3703ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (stmt->tag) {
3704ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3705ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* --------- STORE --------- */
3706ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Ist_Store: {
3707ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRType    tya   = typeOfIRExpr(env->type_env, stmt->Ist.Store.addr);
3708ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRType    tyd   = typeOfIRExpr(env->type_env, stmt->Ist.Store.data);
3709ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IREndness end   = stmt->Ist.Store.end;
3710ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3711ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (tya != Ity_I32 || end != Iend_LE)
3712ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto stmt_fail;
3713ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3714ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (tyd == Ity_I32) {
3715ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         X86AMode* am = iselIntExpr_AMode(env, stmt->Ist.Store.addr);
3716ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         X86RI* ri = iselIntExpr_RI(env, stmt->Ist.Store.data);
3717ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, X86Instr_Alu32M(Xalu_MOV,ri,am));
3718ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
3719ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3720ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (tyd == Ity_I8 || tyd == Ity_I16) {
3721ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         X86AMode* am = iselIntExpr_AMode(env, stmt->Ist.Store.addr);
3722ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg r = iselIntExpr_R(env, stmt->Ist.Store.data);
3723ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, X86Instr_Store( toUChar(tyd==Ity_I8 ? 1 : 2),
3724ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                       r,am ));
3725ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
3726ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3727ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (tyd == Ity_F64) {
3728ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         X86AMode* am = iselIntExpr_AMode(env, stmt->Ist.Store.addr);
3729ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg r = iselDblExpr(env, stmt->Ist.Store.data);
3730ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, X86Instr_FpLdSt(False/*store*/, 8, r, am));
3731ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
3732ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3733ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (tyd == Ity_F32) {
3734ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         X86AMode* am = iselIntExpr_AMode(env, stmt->Ist.Store.addr);
3735ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg r = iselFltExpr(env, stmt->Ist.Store.data);
3736ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, X86Instr_FpLdSt(False/*store*/, 4, r, am));
3737ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
3738ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3739ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (tyd == Ity_I64) {
3740ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg vHi, vLo, rA;
3741ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         iselInt64Expr(&vHi, &vLo, env, stmt->Ist.Store.data);
3742ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         rA = iselIntExpr_R(env, stmt->Ist.Store.addr);
3743ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, X86Instr_Alu32M(
3744ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          Xalu_MOV, X86RI_Reg(vLo), X86AMode_IR(0, rA)));
3745ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, X86Instr_Alu32M(
3746ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          Xalu_MOV, X86RI_Reg(vHi), X86AMode_IR(4, rA)));
3747ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
3748ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3749ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (tyd == Ity_V128) {
3750ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         X86AMode* am = iselIntExpr_AMode(env, stmt->Ist.Store.addr);
3751ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg r = iselVecExpr(env, stmt->Ist.Store.data);
3752ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, X86Instr_SseLdSt(False/*store*/, r, am));
3753ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
3754ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3755ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
3756ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3757ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3758ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* --------- PUT --------- */
3759ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Ist_Put: {
3760ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRType ty = typeOfIRExpr(env->type_env, stmt->Ist.Put.data);
3761ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (ty == Ity_I32) {
3762ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* We're going to write to memory, so compute the RHS into an
3763ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            X86RI. */
3764ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         X86RI* ri = iselIntExpr_RI(env, stmt->Ist.Put.data);
3765ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env,
3766ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  X86Instr_Alu32M(
3767ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     Xalu_MOV,
3768ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     ri,
3769ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     X86AMode_IR(stmt->Ist.Put.offset,hregX86_EBP())
3770ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 ));
3771ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
3772ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3773ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (ty == Ity_I8 || ty == Ity_I16) {
3774ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg r = iselIntExpr_R(env, stmt->Ist.Put.data);
3775ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, X86Instr_Store(
3776ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          toUChar(ty==Ity_I8 ? 1 : 2),
3777ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          r,
3778ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          X86AMode_IR(stmt->Ist.Put.offset,
3779ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                      hregX86_EBP())));
3780ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
3781ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3782ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (ty == Ity_I64) {
3783ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg vHi, vLo;
3784ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         X86AMode* am  = X86AMode_IR(stmt->Ist.Put.offset, hregX86_EBP());
3785ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         X86AMode* am4 = advance4(am);
3786ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         iselInt64Expr(&vHi, &vLo, env, stmt->Ist.Put.data);
3787ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, X86Instr_Alu32M( Xalu_MOV, X86RI_Reg(vLo), am ));
3788ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, X86Instr_Alu32M( Xalu_MOV, X86RI_Reg(vHi), am4 ));
3789ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
3790ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3791ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (ty == Ity_V128) {
3792ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg      vec = iselVecExpr(env, stmt->Ist.Put.data);
3793ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         X86AMode* am  = X86AMode_IR(stmt->Ist.Put.offset, hregX86_EBP());
3794ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, X86Instr_SseLdSt(False/*store*/, vec, am));
3795ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
3796ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3797ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (ty == Ity_F32) {
3798ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg f32 = iselFltExpr(env, stmt->Ist.Put.data);
3799ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         X86AMode* am  = X86AMode_IR(stmt->Ist.Put.offset, hregX86_EBP());
3800ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         set_FPU_rounding_default(env); /* paranoia */
3801ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, X86Instr_FpLdSt( False/*store*/, 4, f32, am ));
3802ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
3803ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3804ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (ty == Ity_F64) {
3805ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg f64 = iselDblExpr(env, stmt->Ist.Put.data);
3806ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         X86AMode* am  = X86AMode_IR(stmt->Ist.Put.offset, hregX86_EBP());
3807ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         set_FPU_rounding_default(env); /* paranoia */
3808ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, X86Instr_FpLdSt( False/*store*/, 8, f64, am ));
3809ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
3810ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3811ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
3812ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3813ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3814ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* --------- Indexed PUT --------- */
3815ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Ist_PutI: {
3816ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      X86AMode* am
3817ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         = genGuestArrayOffset(
3818ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              env, stmt->Ist.PutI.descr,
3819ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   stmt->Ist.PutI.ix, stmt->Ist.PutI.bias );
3820ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3821ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRType ty = typeOfIRExpr(env->type_env, stmt->Ist.PutI.data);
3822ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (ty == Ity_F64) {
3823ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg val = iselDblExpr(env, stmt->Ist.PutI.data);
3824ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, X86Instr_FpLdSt( False/*store*/, 8, val, am ));
3825ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
3826ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3827ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (ty == Ity_I8) {
3828ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg r = iselIntExpr_R(env, stmt->Ist.PutI.data);
3829ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, X86Instr_Store( 1, r, am ));
3830ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
3831ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3832ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (ty == Ity_I32) {
3833ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg r = iselIntExpr_R(env, stmt->Ist.PutI.data);
3834ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, X86Instr_Alu32M( Xalu_MOV, X86RI_Reg(r), am ));
3835ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
3836ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3837ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (ty == Ity_I64) {
3838ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg rHi, rLo;
3839ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         X86AMode* am4 = advance4(am);
3840ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         iselInt64Expr(&rHi, &rLo, env, stmt->Ist.PutI.data);
3841ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, X86Instr_Alu32M( Xalu_MOV, X86RI_Reg(rLo), am ));
3842ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, X86Instr_Alu32M( Xalu_MOV, X86RI_Reg(rHi), am4 ));
3843ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
3844ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3845ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
3846ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3847ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3848ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* --------- TMP --------- */
3849ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Ist_WrTmp: {
3850ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp tmp = stmt->Ist.WrTmp.tmp;
3851ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRType ty = typeOfIRTemp(env->type_env, tmp);
3852ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3853ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* optimisation: if stmt->Ist.WrTmp.data is Add32(..,..),
3854ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         compute it into an AMode and then use LEA.  This usually
3855ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         produces fewer instructions, often because (for memcheck
3856ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         created IR) we get t = address-expression, (t is later used
3857ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         twice) and so doing this naturally turns address-expression
3858ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         back into an X86 amode. */
3859ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (ty == Ity_I32
3860ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          && stmt->Ist.WrTmp.data->tag == Iex_Binop
3861ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          && stmt->Ist.WrTmp.data->Iex.Binop.op == Iop_Add32) {
3862ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         X86AMode* am = iselIntExpr_AMode(env, stmt->Ist.WrTmp.data);
3863ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg dst = lookupIRTemp(env, tmp);
3864ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (am->tag == Xam_IR && am->Xam.IR.imm == 0) {
3865ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* Hmm, iselIntExpr_AMode wimped out and just computed the
3866ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               value into a register.  Just emit a normal reg-reg move
3867ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               so reg-alloc can coalesce it away in the usual way. */
3868ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg src = am->Xam.IR.reg;
3869ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, X86Instr_Alu32R(Xalu_MOV, X86RMI_Reg(src), dst));
3870ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
3871ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, X86Instr_Lea32(am,dst));
3872ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
3873ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
3874ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3875ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3876ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (ty == Ity_I32 || ty == Ity_I16 || ty == Ity_I8) {
3877ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         X86RMI* rmi = iselIntExpr_RMI(env, stmt->Ist.WrTmp.data);
3878ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg dst = lookupIRTemp(env, tmp);
3879ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, X86Instr_Alu32R(Xalu_MOV,rmi,dst));
3880ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
3881ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3882ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (ty == Ity_I64) {
3883ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg rHi, rLo, dstHi, dstLo;
3884ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         iselInt64Expr(&rHi,&rLo, env, stmt->Ist.WrTmp.data);
3885ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         lookupIRTemp64( &dstHi, &dstLo, env, tmp);
3886ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, mk_iMOVsd_RR(rHi,dstHi) );
3887ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, mk_iMOVsd_RR(rLo,dstLo) );
3888ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
3889ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3890ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (ty == Ity_I1) {
3891ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         X86CondCode cond = iselCondCode(env, stmt->Ist.WrTmp.data);
3892ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg dst = lookupIRTemp(env, tmp);
3893ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, X86Instr_Set32(cond, dst));
3894ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
3895ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3896ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (ty == Ity_F64) {
3897ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg dst = lookupIRTemp(env, tmp);
3898ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg src = iselDblExpr(env, stmt->Ist.WrTmp.data);
3899ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, X86Instr_FpUnary(Xfp_MOV,src,dst));
3900ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
3901ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3902ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (ty == Ity_F32) {
3903ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg dst = lookupIRTemp(env, tmp);
3904ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg src = iselFltExpr(env, stmt->Ist.WrTmp.data);
3905ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, X86Instr_FpUnary(Xfp_MOV,src,dst));
3906ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
3907ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3908ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (ty == Ity_V128) {
3909ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg dst = lookupIRTemp(env, tmp);
3910ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg src = iselVecExpr(env, stmt->Ist.WrTmp.data);
3911ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, mk_vMOVsd_RR(src,dst));
3912ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
3913ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3914ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
3915ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3916ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3917ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* --------- Call to DIRTY helper --------- */
3918ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Ist_Dirty: {
3919ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRType   retty;
3920ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRDirty* d = stmt->Ist.Dirty.details;
3921ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Bool     passBBP = False;
3922ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3923ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (d->nFxState == 0)
3924ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(!d->needsBBP);
3925ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3926ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      passBBP = toBool(d->nFxState > 0 && d->needsBBP);
3927ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3928ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Marshal args, do the call, clear stack. */
3929ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      doHelperCall( env, passBBP, d->guard, d->cee, d->args );
3930ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3931ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Now figure out what to do with the returned value, if any. */
3932ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (d->tmp == IRTemp_INVALID)
3933ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* No return value.  Nothing to do. */
3934ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
3935ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3936ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      retty = typeOfIRTemp(env->type_env, d->tmp);
3937ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (retty == Ity_I64) {
3938ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg dstHi, dstLo;
3939ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* The returned value is in %edx:%eax.  Park it in the
3940ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            register-pair associated with tmp. */
3941ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         lookupIRTemp64( &dstHi, &dstLo, env, d->tmp);
3942ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, mk_iMOVsd_RR(hregX86_EDX(),dstHi) );
3943ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, mk_iMOVsd_RR(hregX86_EAX(),dstLo) );
3944ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
3945ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3946ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (retty == Ity_I32 || retty == Ity_I16 || retty == Ity_I8) {
3947ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* The returned value is in %eax.  Park it in the register
3948ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            associated with tmp. */
3949ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg dst = lookupIRTemp(env, d->tmp);
3950ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, mk_iMOVsd_RR(hregX86_EAX(),dst) );
3951ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
3952ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3953ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
3954ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3955ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3956ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* --------- MEM FENCE --------- */
3957ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Ist_MBE:
3958ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch (stmt->Ist.MBE.event) {
3959ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Imbe_Fence:
3960ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, X86Instr_MFence(env->hwcaps));
3961ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return;
3962ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         default:
3963ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
3964ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3965ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
3966ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3967ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* --------- ACAS --------- */
3968ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Ist_CAS:
3969ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (stmt->Ist.CAS.details->oldHi == IRTemp_INVALID) {
3970ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* "normal" singleton CAS */
3971ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         UChar  sz;
3972ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRCAS* cas = stmt->Ist.CAS.details;
3973ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRType ty  = typeOfIRExpr(env->type_env, cas->dataLo);
3974ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* get: cas->expdLo into %eax, and cas->dataLo into %ebx */
3975ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         X86AMode* am = iselIntExpr_AMode(env, cas->addr);
3976ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg rDataLo = iselIntExpr_R(env, cas->dataLo);
3977ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg rExpdLo = iselIntExpr_R(env, cas->expdLo);
3978ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg rOldLo  = lookupIRTemp(env, cas->oldLo);
3979ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(cas->expdHi == NULL);
3980ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(cas->dataHi == NULL);
3981ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, mk_iMOVsd_RR(rExpdLo, rOldLo));
3982ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, mk_iMOVsd_RR(rExpdLo, hregX86_EAX()));
3983ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, mk_iMOVsd_RR(rDataLo, hregX86_EBX()));
3984ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         switch (ty) {
3985ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Ity_I32: sz = 4; break;
3986ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Ity_I16: sz = 2; break;
3987ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Ity_I8:  sz = 1; break;
3988ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            default: goto unhandled_cas;
3989ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
3990ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, X86Instr_ACAS(am, sz));
3991ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env,
3992ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  X86Instr_CMov32(Xcc_NZ,
3993ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                  X86RM_Reg(hregX86_EAX()), rOldLo));
3994ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
3995ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else {
3996ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* double CAS */
3997ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRCAS* cas = stmt->Ist.CAS.details;
3998ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRType ty  = typeOfIRExpr(env->type_env, cas->dataLo);
3999ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* only 32-bit allowed in this case */
4000ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* get: cas->expdLo into %eax, and cas->dataLo into %ebx */
4001ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* get: cas->expdHi into %edx, and cas->dataHi into %ecx */
4002ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         X86AMode* am = iselIntExpr_AMode(env, cas->addr);
4003ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg rDataHi = iselIntExpr_R(env, cas->dataHi);
4004ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg rDataLo = iselIntExpr_R(env, cas->dataLo);
4005ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg rExpdHi = iselIntExpr_R(env, cas->expdHi);
4006ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg rExpdLo = iselIntExpr_R(env, cas->expdLo);
4007ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg rOldHi  = lookupIRTemp(env, cas->oldHi);
4008ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg rOldLo  = lookupIRTemp(env, cas->oldLo);
4009ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (ty != Ity_I32)
4010ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto unhandled_cas;
4011ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, mk_iMOVsd_RR(rExpdHi, rOldHi));
4012ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, mk_iMOVsd_RR(rExpdLo, rOldLo));
4013ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, mk_iMOVsd_RR(rExpdHi, hregX86_EDX()));
4014ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, mk_iMOVsd_RR(rExpdLo, hregX86_EAX()));
4015ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, mk_iMOVsd_RR(rDataHi, hregX86_ECX()));
4016ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, mk_iMOVsd_RR(rDataLo, hregX86_EBX()));
4017ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, X86Instr_DACAS(am));
4018ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env,
4019ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  X86Instr_CMov32(Xcc_NZ,
4020ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                  X86RM_Reg(hregX86_EDX()), rOldHi));
4021ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env,
4022ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  X86Instr_CMov32(Xcc_NZ,
4023ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                  X86RM_Reg(hregX86_EAX()), rOldLo));
4024ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
4025ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
4026ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      unhandled_cas:
4027ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
4028ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4029ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* --------- INSTR MARK --------- */
4030ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Doesn't generate any executable code ... */
4031ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Ist_IMark:
4032ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       return;
4033ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4034ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* --------- NO-OP --------- */
4035ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Fairly self-explanatory, wouldn't you say? */
4036ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Ist_NoOp:
4037ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       return;
4038ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4039ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* --------- EXIT --------- */
4040ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Ist_Exit: {
4041ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      X86RI*      dst;
4042ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      X86CondCode cc;
4043ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (stmt->Ist.Exit.dst->tag != Ico_U32)
4044ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vpanic("isel_x86: Ist_Exit: dst is not a 32-bit value");
4045ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      dst = iselIntExpr_RI(env, IRExpr_Const(stmt->Ist.Exit.dst));
4046ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      cc  = iselCondCode(env,stmt->Ist.Exit.guard);
4047ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env, X86Instr_Goto(stmt->Ist.Exit.jk, cc, dst));
4048ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return;
4049ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
4050ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4051ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   default: break;
4052ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
4053ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  stmt_fail:
4054ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ppIRStmt(stmt);
4055ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vpanic("iselStmt");
4056ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4057ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4058ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4059ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------*/
4060ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- ISEL: Basic block terminators (Nexts)             ---*/
4061ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------*/
4062ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4063ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void iselNext ( ISelEnv* env, IRExpr* next, IRJumpKind jk )
4064ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
4065ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   X86RI* ri;
4066ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (vex_traceflags & VEX_TRACE_VCODE) {
4067ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vex_printf("\n-- goto {");
4068ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ppIRJumpKind(jk);
4069ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vex_printf("} ");
4070ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ppIRExpr(next);
4071ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vex_printf("\n");
4072ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
4073ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ri = iselIntExpr_RI(env, next);
4074ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   addInstr(env, X86Instr_Goto(jk, Xcc_ALWAYS,ri));
4075ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4076ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4077ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4078ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------*/
4079ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Insn selector top-level                           ---*/
4080ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------*/
4081ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4082ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Translate an entire SB to x86 code. */
4083ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4084ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownHInstrArray* iselSB_X86 ( IRSB* bb, VexArch      arch_host,
4085ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                    VexArchInfo* archinfo_host,
4086ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                    VexAbiInfo*  vbi/*UNUSED*/ )
4087ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
4088ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int      i, j;
4089ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   HReg     hreg, hregHI;
4090ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ISelEnv* env;
4091ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt     hwcaps_host = archinfo_host->hwcaps;
4092ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4093ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* sanity ... */
4094ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(arch_host == VexArchX86);
4095ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(0 == (hwcaps_host
4096ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 & ~(VEX_HWCAPS_X86_SSE1
4097ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     | VEX_HWCAPS_X86_SSE2
4098ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     | VEX_HWCAPS_X86_SSE3
4099ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     | VEX_HWCAPS_X86_LZCNT)));
4100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Make up an initial environment to use. */
4102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   env = LibVEX_Alloc(sizeof(ISelEnv));
4103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   env->vreg_ctr = 0;
4104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Set up output code array. */
4106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   env->code = newHInstrArray();
4107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Copy BB's type env. */
4109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   env->type_env = bb->tyenv;
4110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Make up an IRTemp -> virtual HReg mapping.  This doesn't
4112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      change as we go along. */
4113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   env->n_vregmap = bb->tyenv->types_used;
4114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   env->vregmap   = LibVEX_Alloc(env->n_vregmap * sizeof(HReg));
4115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   env->vregmapHI = LibVEX_Alloc(env->n_vregmap * sizeof(HReg));
4116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* and finally ... */
4118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   env->hwcaps = hwcaps_host;
4119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* For each IR temporary, allocate a suitably-kinded virtual
4121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      register. */
4122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   j = 0;
4123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (i = 0; i < env->n_vregmap; i++) {
4124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      hregHI = hreg = INVALID_HREG;
4125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch (bb->tyenv->types[i]) {
4126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Ity_I1:
4127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Ity_I8:
4128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Ity_I16:
4129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Ity_I32:  hreg   = mkHReg(j++, HRcInt32, True); break;
4130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Ity_I64:  hreg   = mkHReg(j++, HRcInt32, True);
4131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        hregHI = mkHReg(j++, HRcInt32, True); break;
4132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Ity_F32:
4133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Ity_F64:  hreg   = mkHReg(j++, HRcFlt64, True); break;
4134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Ity_V128: hreg   = mkHReg(j++, HRcVec128, True); break;
4135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         default: ppIRType(bb->tyenv->types[i]);
4136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  vpanic("iselBB: IRTemp type");
4137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
4138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      env->vregmap[i]   = hreg;
4139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      env->vregmapHI[i] = hregHI;
4140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
4141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   env->vreg_ctr = j;
4142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Ok, finally we can iterate over the statements. */
4144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (i = 0; i < bb->stmts_used; i++)
4145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      iselStmt(env,bb->stmts[i]);
4146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   iselNext(env,bb->next,bb->jumpkind);
4148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* record the number of vregs we used. */
4150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   env->code->n_vregs = env->vreg_ctr;
4151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return env->code;
4152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------------*/
4156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- end                                     host_x86_isel.c ---*/
4157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------------*/
4158