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