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
10663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   Copyright (C) 2004-2012 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
115663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   - The host subarchitecture we are selecting insns for.
116663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng     This is set at the start and does not change.
117663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   - The code array, that is, the insns selected so far.
119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   - A counter, for generating new virtual registers.
121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
122663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   - A Bool for indicating whether we may generate chain-me
123663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng     instructions for control flow transfers, or whether we must use
124663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng     XAssisted.
125663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
126663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   - The maximum guest address of any guest insn in this block.
127663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng     Actually, the address of the highest-addressed byte from any insn
128663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng     in this block.  Is set at the start and does not change.  This is
129663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng     used for detecting jumps which are definitely forward-edges from
130663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng     this block, and therefore can be made (chained) to the fast entry
131663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng     point of the destination, thereby avoiding the destination's
132663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng     event check.
133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Note, this is all host-independent.  (JRS 20050201: well, kinda
135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ... not completely.  Compare with ISelEnv for X86.)
136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef
139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   struct {
140663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* Constant -- are set at the start and do not change. */
141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTypeEnv*   type_env;
142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HReg*        vregmap;
144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HReg*        vregmapHI;
145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Int          n_vregmap;
146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
147663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      UInt         hwcaps;
148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
149663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      Bool         chainingAllowed;
150663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      Addr64       max_ga;
151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
152663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* These are modified as we go along. */
153663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      HInstrArray* code;
154663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      Int          vreg_ctr;
155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ISelEnv;
157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic HReg lookupIRTemp ( ISelEnv* env, IRTemp tmp )
160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(tmp >= 0);
162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(tmp < env->n_vregmap);
163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return env->vregmap[tmp];
164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
166663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic void lookupIRTempPair ( HReg* vrHI, HReg* vrLO,
167663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                               ISelEnv* env, IRTemp tmp )
168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(tmp >= 0);
170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(tmp < env->n_vregmap);
171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(env->vregmapHI[tmp] != INVALID_HREG);
172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   *vrLO = env->vregmap[tmp];
173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   *vrHI = env->vregmapHI[tmp];
174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void addInstr ( ISelEnv* env, AMD64Instr* instr )
177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   addHInstr(env->code, instr);
179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (vex_traceflags & VEX_TRACE_VCODE) {
180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ppAMD64Instr(instr, True);
181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vex_printf("\n");
182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic HReg newVRegI ( ISelEnv* env )
186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   HReg reg = mkHReg(env->vreg_ctr, HRcInt64, True/*virtual reg*/);
188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   env->vreg_ctr++;
189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return reg;
190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic HReg newVRegV ( ISelEnv* env )
193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   HReg reg = mkHReg(env->vreg_ctr, HRcVec128, True/*virtual reg*/);
195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   env->vreg_ctr++;
196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return reg;
197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------*/
201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- ISEL: Forward declarations                        ---*/
202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------*/
203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* These are organised as iselXXX and iselXXX_wrk pairs.  The
205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   iselXXX_wrk do the real work, but are not to be called directly.
206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   For each XXX, iselXXX calls its iselXXX_wrk counterpart, then
207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   checks that all returned registers are virtual.  You should not
208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   call the _wrk version directly.
209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic AMD64RMI*     iselIntExpr_RMI_wrk ( ISelEnv* env, IRExpr* e );
211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic AMD64RMI*     iselIntExpr_RMI     ( ISelEnv* env, IRExpr* e );
212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic AMD64RI*      iselIntExpr_RI_wrk  ( ISelEnv* env, IRExpr* e );
214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic AMD64RI*      iselIntExpr_RI      ( ISelEnv* env, IRExpr* e );
215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic AMD64RM*      iselIntExpr_RM_wrk  ( ISelEnv* env, IRExpr* e );
217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic AMD64RM*      iselIntExpr_RM      ( ISelEnv* env, IRExpr* e );
218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic HReg          iselIntExpr_R_wrk   ( ISelEnv* env, IRExpr* e );
220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic HReg          iselIntExpr_R       ( ISelEnv* env, IRExpr* e );
221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic AMD64AMode*   iselIntExpr_AMode_wrk ( ISelEnv* env, IRExpr* e );
223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic AMD64AMode*   iselIntExpr_AMode     ( ISelEnv* env, IRExpr* e );
224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
225663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic void          iselInt128Expr_wrk ( /*OUT*/HReg* rHi, HReg* rLo,
226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                          ISelEnv* env, IRExpr* e );
227663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic void          iselInt128Expr     ( /*OUT*/HReg* rHi, HReg* rLo,
228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                          ISelEnv* env, IRExpr* e );
229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic AMD64CondCode iselCondCode_wrk    ( ISelEnv* env, IRExpr* e );
231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic AMD64CondCode iselCondCode        ( ISelEnv* env, IRExpr* e );
232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic HReg          iselDblExpr_wrk     ( ISelEnv* env, IRExpr* e );
234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic HReg          iselDblExpr         ( ISelEnv* env, IRExpr* e );
235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic HReg          iselFltExpr_wrk     ( ISelEnv* env, IRExpr* e );
237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic HReg          iselFltExpr         ( ISelEnv* env, IRExpr* e );
238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic HReg          iselVecExpr_wrk     ( ISelEnv* env, IRExpr* e );
240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic HReg          iselVecExpr         ( ISelEnv* env, IRExpr* e );
241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
242663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic void          iselDVecExpr_wrk ( /*OUT*/HReg* rHi, HReg* rLo,
243663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                        ISelEnv* env, IRExpr* e );
244663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic void          iselDVecExpr     ( /*OUT*/HReg* rHi, HReg* rLo,
245663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                        ISelEnv* env, IRExpr* e );
246663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------*/
249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- ISEL: Misc helpers                                ---*/
250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------*/
251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool sane_AMode ( AMD64AMode* am )
253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (am->tag) {
255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Aam_IR:
256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return
257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            toBool( hregClass(am->Aam.IR.reg) == HRcInt64
258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    && (hregIsVirtual(am->Aam.IR.reg)
259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        || am->Aam.IR.reg == hregAMD64_RBP()) );
260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Aam_IRRS:
261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return
262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            toBool( hregClass(am->Aam.IRRS.base) == HRcInt64
263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    && hregIsVirtual(am->Aam.IRRS.base)
264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    && hregClass(am->Aam.IRRS.index) == HRcInt64
265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    && hregIsVirtual(am->Aam.IRRS.index) );
266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        vpanic("sane_AMode: unknown amd64 amode tag");
268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Can the lower 32 bits be signedly widened to produce the whole
273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   64-bit value?  In other words, are the top 33 bits either all 0 or
274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   all 1 ? */
275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool fitsIn32Bits ( ULong x )
276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Long y0 = (Long)x;
278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Long y1 = y0;
279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   y1 <<= 32;
280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   y1 >>=/*s*/ 32;
281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return toBool(x == y1);
282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Is this a 64-bit zero expression? */
285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool isZeroU64 ( IRExpr* e )
287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return e->tag == Iex_Const
289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          && e->Iex.Const.con->tag == Ico_U64
290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          && e->Iex.Const.con->Ico.U64 == 0ULL;
291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool isZeroU32 ( IRExpr* e )
294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return e->tag == Iex_Const
296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          && e->Iex.Const.con->tag == Ico_U32
297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          && e->Iex.Const.con->Ico.U32 == 0;
298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Make a int reg-reg move. */
301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic AMD64Instr* mk_iMOVsd_RR ( HReg src, HReg dst )
303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(hregClass(src) == HRcInt64);
305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(hregClass(dst) == HRcInt64);
306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return AMD64Instr_Alu64R(Aalu_MOV, AMD64RMI_Reg(src), dst);
307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
309663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* Make a vector (128 bit) reg-reg move. */
310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic AMD64Instr* mk_vMOVsd_RR ( HReg src, HReg dst )
312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(hregClass(src) == HRcVec128);
314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(hregClass(dst) == HRcVec128);
315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return AMD64Instr_SseReRg(Asse_MOV, src, dst);
316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Advance/retreat %rsp by n. */
319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void add_to_rsp ( ISelEnv* env, Int n )
321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(n > 0 && n < 256 && (n%8) == 0);
323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   addInstr(env,
324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            AMD64Instr_Alu64R(Aalu_ADD, AMD64RMI_Imm(n),
325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                        hregAMD64_RSP()));
326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void sub_from_rsp ( ISelEnv* env, Int n )
329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(n > 0 && n < 256 && (n%8) == 0);
331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   addInstr(env,
332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            AMD64Instr_Alu64R(Aalu_SUB, AMD64RMI_Imm(n),
333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                        hregAMD64_RSP()));
334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Push 64-bit constants on the stack. */
337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void push_uimm64( ISelEnv* env, ULong uimm64 )
338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* If uimm64 can be expressed as the sign extension of its
340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      lower 32 bits, we can do it the easy way. */
341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Long simm64 = (Long)uimm64;
342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if ( simm64 == ((simm64 << 32) >> 32) ) {
343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr( env, AMD64Instr_Push(AMD64RMI_Imm( (UInt)uimm64 )) );
344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HReg tmp = newVRegI(env);
346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr( env, AMD64Instr_Imm64(uimm64, tmp) );
347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr( env, AMD64Instr_Push(AMD64RMI_Reg(tmp)) );
348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Used only in doHelperCall.  If possible, produce a single
353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   instruction which computes 'e' into 'dst'.  If not possible, return
354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   NULL. */
355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic AMD64Instr* iselIntExpr_single_instruction ( ISelEnv* env,
357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                                    HReg     dst,
358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                                    IRExpr*  e )
359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(typeOfIRExpr(env->type_env, e) == Ity_I64);
361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_Const) {
363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert(e->Iex.Const.con->tag == Ico_U64);
364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (fitsIn32Bits(e->Iex.Const.con->Ico.U64)) {
365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return AMD64Instr_Alu64R(
366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   Aalu_MOV,
367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   AMD64RMI_Imm(toUInt(e->Iex.Const.con->Ico.U64)),
368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   dst
369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                );
370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else {
371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return AMD64Instr_Imm64(e->Iex.Const.con->Ico.U64, dst);
372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_RdTmp) {
376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HReg src = lookupIRTemp(env, e->Iex.RdTmp.tmp);
377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return mk_iMOVsd_RR(src, dst);
378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_Get) {
381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert(e->Iex.Get.ty == Ity_I64);
382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return AMD64Instr_Alu64R(
383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                Aalu_MOV,
384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                AMD64RMI_Mem(
385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   AMD64AMode_IR(e->Iex.Get.offset,
386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                 hregAMD64_RBP())),
387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                dst);
388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_Unop
391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && e->Iex.Unop.op == Iop_32Uto64
392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && e->Iex.Unop.arg->tag == Iex_RdTmp) {
393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HReg src = lookupIRTemp(env, e->Iex.Unop.arg->Iex.RdTmp.tmp);
394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return AMD64Instr_MovxLQ(False, src, dst);
395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (0) { ppIRExpr(e); vex_printf("\n"); }
398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return NULL;
400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Do a complete function call.  guard is a Ity_Bit expression
404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   indicating whether or not the call happens.  If guard==NULL, the
405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   call is unconditional. */
406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid doHelperCall ( ISelEnv* env,
409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    Bool passBBP,
410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    IRExpr* guard, IRCallee* cee, IRExpr** args )
411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   AMD64CondCode cc;
413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   HReg          argregs[6];
414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   HReg          tmpregs[6];
415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   AMD64Instr*   fastinstrs[6];
416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int           n_args, i, argreg;
417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Marshal args for a call and do the call.
419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      If passBBP is True, %rbp (the baseblock pointer) is to be passed
421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      as the first arg.
422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      This function only deals with a tiny set of possibilities, which
424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      cover all helpers in practice.  The restrictions are that only
425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      arguments in registers are supported, hence only 6x64 integer
426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      bits in total can be passed.  In fact the only supported arg
427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      type is I64.
428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Generating code which is both efficient and correct when
430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      parameters are to be passed in registers is difficult, for the
431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      reasons elaborated in detail in comments attached to
432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      doHelperCall() in priv/host-x86/isel.c.  Here, we use a variant
433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      of the method described in those comments.
434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      The problem is split into two cases: the fast scheme and the
436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      slow scheme.  In the fast scheme, arguments are computed
437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      directly into the target (real) registers.  This is only safe
438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      when we can be sure that computation of each argument will not
439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      trash any real registers set by computation of any other
440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      argument.
441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      In the slow scheme, all args are first computed into vregs, and
443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      once they are all done, they are moved to the relevant real
444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      regs.  This always gives correct code, but it also gives a bunch
445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      of vreg-to-rreg moves which are usually redundant but are hard
446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      for the register allocator to get rid of.
447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      To decide which scheme to use, all argument expressions are
449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      first examined.  If they are all so simple that it is clear they
450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      will be evaluated without use of any fixed registers, use the
451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      fast scheme, else use the slow scheme.  Note also that only
452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      unconditional calls may use the fast scheme, since having to
453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      compute a condition expression could itself trash real
454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      registers.
455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Note this requires being able to examine an expression and
457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      determine whether or not evaluation of it might use a fixed
458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      register.  That requires knowledge of how the rest of this insn
459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      selector works.  Currently just the following 3 are regarded as
460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      safe -- hopefully they cover the majority of arguments in
461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      practice: IRExpr_Tmp IRExpr_Const IRExpr_Get.
462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   */
463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Note that the cee->regparms field is meaningless on AMD64 host
465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      (since there is only one calling convention) and so we always
466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ignore it. */
467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   n_args = 0;
469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (i = 0; args[i]; i++)
470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      n_args++;
471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (6 < n_args + (passBBP ? 1 : 0))
473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vpanic("doHelperCall(AMD64): cannot currently handle > 6 args");
474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   argregs[0] = hregAMD64_RDI();
476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   argregs[1] = hregAMD64_RSI();
477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   argregs[2] = hregAMD64_RDX();
478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   argregs[3] = hregAMD64_RCX();
479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   argregs[4] = hregAMD64_R8();
480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   argregs[5] = hregAMD64_R9();
481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tmpregs[0] = tmpregs[1] = tmpregs[2] =
483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tmpregs[3] = tmpregs[4] = tmpregs[5] = INVALID_HREG;
484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   fastinstrs[0] = fastinstrs[1] = fastinstrs[2] =
486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   fastinstrs[3] = fastinstrs[4] = fastinstrs[5] = NULL;
487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* First decide which scheme (slow or fast) is to be used.  First
489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assume the fast scheme, and select slow if any contraindications
490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      (wow) appear. */
491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (guard) {
493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (guard->tag == Iex_Const
494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          && guard->Iex.Const.con->tag == Ico_U1
495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          && guard->Iex.Const.con->Ico.U1 == True) {
496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* unconditional */
497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else {
498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Not manifestly unconditional -- be conservative. */
499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto slowscheme;
500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Ok, let's try for the fast scheme.  If it doesn't pan out, we'll
504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      use the slow scheme.  Because this is tentative, we can't call
505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr (that is, commit to) any instructions until we're
506ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      handled all the arguments.  So park the resulting instructions
507ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      in a buffer and emit that if we're successful. */
508ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* FAST SCHEME */
510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   argreg = 0;
511ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (passBBP) {
512ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      fastinstrs[argreg] = mk_iMOVsd_RR( hregAMD64_RBP(), argregs[argreg]);
513ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      argreg++;
514ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
515ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
516ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (i = 0; i < n_args; i++) {
517ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert(argreg < 6);
518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert(typeOfIRExpr(env->type_env, args[i]) == Ity_I64);
519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      fastinstrs[argreg]
520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         = iselIntExpr_single_instruction( env, argregs[argreg], args[i] );
521ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (fastinstrs[argreg] == NULL)
522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto slowscheme;
523ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      argreg++;
524ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
525ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
526ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Looks like we're in luck.  Emit the accumulated instructions and
527ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      move on to doing the call itself. */
528ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(argreg <= 6);
529ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (i = 0; i < argreg; i++)
530ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env, fastinstrs[i]);
531ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
532ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Fast scheme only applies for unconditional calls.  Hence: */
533ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   cc = Acc_ALWAYS;
534ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
535ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   goto handle_call;
536ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
537ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
538ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* SLOW SCHEME; move via temporaries */
539ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  slowscheme:
540663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#  if 0 /* debug only */
541663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (n_args > 0) {for (i = 0; args[i]; i++) {
542663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   ppIRExpr(args[i]); vex_printf(" "); }
543663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vex_printf("\n");}
544663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#  endif
545ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   argreg = 0;
546ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
547ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (passBBP) {
548ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* This is pretty stupid; better to move directly to rdi
549ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         after the rest of the args are done. */
550ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      tmpregs[argreg] = newVRegI(env);
551ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env, mk_iMOVsd_RR( hregAMD64_RBP(), tmpregs[argreg]));
552ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      argreg++;
553ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
554ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (i = 0; i < n_args; i++) {
556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert(argreg < 6);
557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert(typeOfIRExpr(env->type_env, args[i]) == Ity_I64);
558ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      tmpregs[argreg] = iselIntExpr_R(env, args[i]);
559ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      argreg++;
560ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
561ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Now we can compute the condition.  We can't do it earlier
563ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      because the argument computations could trash the condition
564ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      codes.  Be a bit clever to handle the common case where the
565ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      guard is 1:Bit. */
566ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   cc = Acc_ALWAYS;
567ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (guard) {
568ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (guard->tag == Iex_Const
569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          && guard->Iex.Const.con->tag == Ico_U1
570ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          && guard->Iex.Const.con->Ico.U1 == True) {
571ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* unconditional -- do nothing */
572ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else {
573ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         cc = iselCondCode( env, guard );
574ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Move the args to their final destinations. */
578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (i = 0; i < argreg; i++) {
579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* None of these insns, including any spill code that might
580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         be generated, may alter the condition codes. */
581ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr( env, mk_iMOVsd_RR( tmpregs[i], argregs[i] ) );
582ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
584ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Finally, the call itself. */
586ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  handle_call:
587ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   addInstr(env, AMD64Instr_Call(
588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    cc,
589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    Ptr_to_ULong(cee->addr),
590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    n_args + (passBBP ? 1 : 0)
591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 )
592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   );
593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Given a guest-state array descriptor, an index expression and a
597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   bias, generate an AMD64AMode holding the relevant guest state
598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   offset. */
599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownAMD64AMode* genGuestArrayOffset ( ISelEnv* env, IRRegArray* descr,
602ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                  IRExpr* off, Int bias )
603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   HReg tmp, roff;
605ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int  elemSz = sizeofIRType(descr->elemTy);
606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int  nElems = descr->nElems;
607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
608ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Throw out any cases not generated by an amd64 front end.  In
609ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      theory there might be a day where we need to handle them -- if
610ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      we ever run non-amd64-guest on amd64 host. */
611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
612ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (nElems != 8 || (elemSz != 1 && elemSz != 8))
613ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vpanic("genGuestArrayOffset(amd64 host)");
614ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
615ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Compute off into a reg, %off.  Then return:
616ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
617ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         movq %off, %tmp
618ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addq $bias, %tmp  (if bias != 0)
619ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         andq %tmp, 7
620ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ... base(%rbp, %tmp, shift) ...
621ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   */
622ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tmp  = newVRegI(env);
623ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   roff = iselIntExpr_R(env, off);
624ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   addInstr(env, mk_iMOVsd_RR(roff, tmp));
625ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (bias != 0) {
626ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Make sure the bias is sane, in the sense that there are
627ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         no significant bits above bit 30 in it. */
628ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert(-10000 < bias && bias < 10000);
629ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env,
630ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               AMD64Instr_Alu64R(Aalu_ADD, AMD64RMI_Imm(bias), tmp));
631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   addInstr(env,
633ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            AMD64Instr_Alu64R(Aalu_AND, AMD64RMI_Imm(7), tmp));
634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(elemSz == 1 || elemSz == 8);
635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return
636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      AMD64AMode_IRRS( descr->base, hregAMD64_RBP(), tmp,
637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                    elemSz==8 ? 3 : 0);
638ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
639ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
640ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
641ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Set the SSE unit's rounding mode to default (%mxcsr = 0x1F80) */
642ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
643ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid set_SSE_rounding_default ( ISelEnv* env )
644ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
645ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* pushq $DEFAULT_MXCSR
646ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ldmxcsr 0(%rsp)
647ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addq $8, %rsp
648ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   */
649ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   AMD64AMode* zero_rsp = AMD64AMode_IR(0, hregAMD64_RSP());
650ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   addInstr(env, AMD64Instr_Push(AMD64RMI_Imm(DEFAULT_MXCSR)));
651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   addInstr(env, AMD64Instr_LdMXCSR(zero_rsp));
652ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   add_to_rsp(env, 8);
653ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
654ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
655ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Mess with the FPU's rounding mode: set to the default rounding mode
656ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   (DEFAULT_FPUCW). */
657ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
658ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid set_FPU_rounding_default ( ISelEnv* env )
659ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
660ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* movq $DEFAULT_FPUCW, -8(%rsp)
661ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      fldcw -8(%esp)
662ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   */
663ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   AMD64AMode* m8_rsp = AMD64AMode_IR(-8, hregAMD64_RSP());
664ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   addInstr(env, AMD64Instr_Alu64M(
665ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    Aalu_MOV, AMD64RI_Imm(DEFAULT_FPUCW), m8_rsp));
666ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   addInstr(env, AMD64Instr_A87LdCW(m8_rsp));
667ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
668ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
669ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
670ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Mess with the SSE unit's rounding mode: 'mode' is an I32-typed
671ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   expression denoting a value in the range 0 .. 3, indicating a round
672ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   mode encoded as per type IRRoundingMode.  Set the SSE machinery to
673ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   have the same rounding.
674ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
675ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
676ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid set_SSE_rounding_mode ( ISelEnv* env, IRExpr* mode )
677ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
678ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Note: this sequence only makes sense because DEFAULT_MXCSR has
679ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      both rounding bits == 0.  If that wasn't the case, we couldn't
680ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      create a new rounding field simply by ORing the new value into
681ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      place. */
682ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
683ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* movq $3, %reg
684ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      andq [[mode]], %reg  -- shouldn't be needed; paranoia
685ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      shlq $13, %reg
686ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      orq $DEFAULT_MXCSR, %reg
687ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      pushq %reg
688ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ldmxcsr 0(%esp)
689ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addq $8, %rsp
690ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   */
691ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   HReg        reg      = newVRegI(env);
692ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   AMD64AMode* zero_rsp = AMD64AMode_IR(0, hregAMD64_RSP());
693ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   addInstr(env, AMD64Instr_Alu64R(Aalu_MOV, AMD64RMI_Imm(3), reg));
694ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   addInstr(env, AMD64Instr_Alu64R(Aalu_AND,
695ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                   iselIntExpr_RMI(env, mode), reg));
696ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   addInstr(env, AMD64Instr_Sh64(Ash_SHL, 13, reg));
697ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   addInstr(env, AMD64Instr_Alu64R(
698ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    Aalu_OR, AMD64RMI_Imm(DEFAULT_MXCSR), reg));
699ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   addInstr(env, AMD64Instr_Push(AMD64RMI_Reg(reg)));
700ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   addInstr(env, AMD64Instr_LdMXCSR(zero_rsp));
701ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   add_to_rsp(env, 8);
702ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
703ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
704ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
705ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Mess with the FPU's rounding mode: 'mode' is an I32-typed
706ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   expression denoting a value in the range 0 .. 3, indicating a round
707ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   mode encoded as per type IRRoundingMode.  Set the x87 FPU to have
708ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   the same rounding.
709ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
710ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
711ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid set_FPU_rounding_mode ( ISelEnv* env, IRExpr* mode )
712ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
713ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   HReg rrm  = iselIntExpr_R(env, mode);
714ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   HReg rrm2 = newVRegI(env);
715ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   AMD64AMode* m8_rsp = AMD64AMode_IR(-8, hregAMD64_RSP());
716ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
717ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* movq  %rrm, %rrm2
718ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      andq  $3, %rrm2   -- shouldn't be needed; paranoia
719ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      shlq  $10, %rrm2
720ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      orq   $DEFAULT_FPUCW, %rrm2
721ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      movq  %rrm2, -8(%rsp)
722ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      fldcw -8(%esp)
723ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   */
724ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   addInstr(env, mk_iMOVsd_RR(rrm, rrm2));
725ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   addInstr(env, AMD64Instr_Alu64R(Aalu_AND, AMD64RMI_Imm(3), rrm2));
726ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   addInstr(env, AMD64Instr_Sh64(Ash_SHL, 10, rrm2));
727ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   addInstr(env, AMD64Instr_Alu64R(Aalu_OR,
728ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                   AMD64RMI_Imm(DEFAULT_FPUCW), rrm2));
729ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   addInstr(env, AMD64Instr_Alu64M(Aalu_MOV,
730ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                   AMD64RI_Reg(rrm2), m8_rsp));
731ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   addInstr(env, AMD64Instr_A87LdCW(m8_rsp));
732ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
733ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
734ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
735ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Generate all-zeroes into a new vector register.
736ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
737ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic HReg generate_zeroes_V128 ( ISelEnv* env )
738ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
739ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   HReg dst = newVRegV(env);
740ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   addInstr(env, AMD64Instr_SseReRg(Asse_XOR, dst, dst));
741ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return dst;
742ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
743ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
744ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Generate all-ones into a new vector register.
745ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
746ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic HReg generate_ones_V128 ( ISelEnv* env )
747ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
748ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   HReg dst = newVRegV(env);
749ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   addInstr(env, AMD64Instr_SseReRg(Asse_CMPEQ32, dst, dst));
750ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return dst;
751ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
752ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
753ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
754ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Generate !src into a new vector register.  Amazing that there isn't
755ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   a less crappy way to do this.
756ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
757ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic HReg do_sse_NotV128 ( ISelEnv* env, HReg src )
758ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
759ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   HReg dst = generate_ones_V128(env);
760ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   addInstr(env, AMD64Instr_SseReRg(Asse_XOR, src, dst));
761ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return dst;
762ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
763ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
764ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
765ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Expand the given byte into a 64-bit word, by cloning each bit
766ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   8 times. */
767ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic ULong bitmask8_to_bytemask64 ( UShort w8 )
768ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
769ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(w8 == (w8 & 0xFF));
770ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ULong w64 = 0;
771ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int i;
772ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (i = 0; i < 8; i++) {
773ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (w8 & (1<<i))
774ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         w64 |= (0xFFULL << (8 * i));
775ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
776ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return w64;
777ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
778ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
779ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
780ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------*/
781ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- ISEL: Integer expressions (64/32/16/8 bit)        ---*/
782ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------*/
783ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
784ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Select insns for an integer-typed expression, and add them to the
785ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   code list.  Return a reg holding the result.  This reg will be a
786ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   virtual register.  THE RETURNED REG MUST NOT BE MODIFIED.  If you
787ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   want to modify it, ask for a new vreg, copy it in there, and modify
788ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   the copy.  The register allocator will do its best to map both
789ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vregs to the same real register, so the copies will often disappear
790ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   later in the game.
791ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
792ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   This should handle expressions of 64, 32, 16 and 8-bit type.  All
793ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   results are returned in a 64-bit register.  For 32-, 16- and 8-bit
794ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   expressions, the upper 32/16/24 bits are arbitrary, so you should
795ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   mask or sign extend partial values if necessary.
796ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
797ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
798ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic HReg iselIntExpr_R ( ISelEnv* env, IRExpr* e )
799ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
800ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   HReg r = iselIntExpr_R_wrk(env, e);
801ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* sanity checks ... */
802ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  if 0
803ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vex_printf("\niselIntExpr_R: "); ppIRExpr(e); vex_printf("\n");
804ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  endif
805ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(hregClass(r) == HRcInt64);
806ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(hregIsVirtual(r));
807ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return r;
808ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
809ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
810ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* DO NOT CALL THIS DIRECTLY ! */
811ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic HReg iselIntExpr_R_wrk ( ISelEnv* env, IRExpr* e )
812ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
813ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Used for unary/binary SIMD64 ops. */
814ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   HWord fn = 0;
815ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Bool second_is_UInt;
816ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
817ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   MatchInfo mi;
818ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   DECLARE_PATTERN(p_1Uto8_64to1);
819ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   DECLARE_PATTERN(p_LDle8_then_8Uto64);
820ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   DECLARE_PATTERN(p_LDle16_then_16Uto64);
821ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
822ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRType ty = typeOfIRExpr(env->type_env,e);
823b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   switch (ty) {
824b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Ity_I64: case Ity_I32: case Ity_I16: case Ity_I8: break;
825b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      default: vassert(0);
826b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   }
827ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
828ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (e->tag) {
829ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
830ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* --------- TEMP --------- */
831ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Iex_RdTmp: {
832ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return lookupIRTemp(env, e->Iex.RdTmp.tmp);
833ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
834ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
835ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* --------- LOAD --------- */
836ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Iex_Load: {
837ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HReg dst = newVRegI(env);
838ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      AMD64AMode* amode = iselIntExpr_AMode ( env, e->Iex.Load.addr );
839ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
840ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* We can't handle big-endian loads, nor load-linked. */
841ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (e->Iex.Load.end != Iend_LE)
842ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto irreducible;
843ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
844ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (ty == Ity_I64) {
845ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, AMD64Instr_Alu64R(Aalu_MOV,
846ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                         AMD64RMI_Mem(amode), dst) );
847ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return dst;
848ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
849ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (ty == Ity_I32) {
850ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, AMD64Instr_LoadEX(4,False,amode,dst));
851ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return dst;
852ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
853ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (ty == Ity_I16) {
854ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, AMD64Instr_LoadEX(2,False,amode,dst));
855ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return dst;
856ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
857ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (ty == Ity_I8) {
858ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, AMD64Instr_LoadEX(1,False,amode,dst));
859ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return dst;
860ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
861ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
862ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
863ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
864ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* --------- BINARY OP --------- */
865ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Iex_Binop: {
866ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      AMD64AluOp   aluOp;
867ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      AMD64ShiftOp shOp;
868ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
869ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Pattern: Sub64(0,x) */
870ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /*     and: Sub32(0,x) */
871ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if ((e->Iex.Binop.op == Iop_Sub64 && isZeroU64(e->Iex.Binop.arg1))
872ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          || (e->Iex.Binop.op == Iop_Sub32 && isZeroU32(e->Iex.Binop.arg1))) {
873ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg dst = newVRegI(env);
874ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg reg = iselIntExpr_R(env, e->Iex.Binop.arg2);
875ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, mk_iMOVsd_RR(reg,dst));
876ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, AMD64Instr_Unary64(Aun_NEG,dst));
877ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return dst;
878ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
879ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
880ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Is it an addition or logical style op? */
881ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch (e->Iex.Binop.op) {
882ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_Add8: case Iop_Add16: case Iop_Add32: case Iop_Add64:
883ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            aluOp = Aalu_ADD; break;
884ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_Sub8: case Iop_Sub16: case Iop_Sub32: case Iop_Sub64:
885ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            aluOp = Aalu_SUB; break;
886ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_And8: case Iop_And16: case Iop_And32: case Iop_And64:
887ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            aluOp = Aalu_AND; break;
888ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_Or8:  case Iop_Or16:  case Iop_Or32:  case Iop_Or64:
889ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            aluOp = Aalu_OR; break;
890ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_Xor8: case Iop_Xor16: case Iop_Xor32: case Iop_Xor64:
891ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            aluOp = Aalu_XOR; break;
892ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_Mul16: case Iop_Mul32: case Iop_Mul64:
893ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            aluOp = Aalu_MUL; break;
894ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         default:
895ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            aluOp = Aalu_INVALID; break;
896ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
897ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* For commutative ops we assume any literal
898ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         values are on the second operand. */
899ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (aluOp != Aalu_INVALID) {
900ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg dst      = newVRegI(env);
901ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg reg      = iselIntExpr_R(env, e->Iex.Binop.arg1);
902ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         AMD64RMI* rmi = iselIntExpr_RMI(env, e->Iex.Binop.arg2);
903ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, mk_iMOVsd_RR(reg,dst));
904ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, AMD64Instr_Alu64R(aluOp, rmi, dst));
905ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return dst;
906ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
907ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
908ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Perhaps a shift op? */
909ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch (e->Iex.Binop.op) {
910ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_Shl64: case Iop_Shl32: case Iop_Shl16: case Iop_Shl8:
911ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            shOp = Ash_SHL; break;
912ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_Shr64: case Iop_Shr32: case Iop_Shr16: case Iop_Shr8:
913ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            shOp = Ash_SHR; break;
914ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_Sar64: case Iop_Sar32: case Iop_Sar16: case Iop_Sar8:
915ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            shOp = Ash_SAR; break;
916ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         default:
917ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            shOp = Ash_INVALID; break;
918ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
919ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (shOp != Ash_INVALID) {
920ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg dst = newVRegI(env);
921ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
922ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* regL = the value to be shifted */
923ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg regL   = iselIntExpr_R(env, e->Iex.Binop.arg1);
924ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, mk_iMOVsd_RR(regL,dst));
925ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
926ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Do any necessary widening for 32/16/8 bit operands */
927ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         switch (e->Iex.Binop.op) {
928ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Iop_Shr64: case Iop_Shl64: case Iop_Sar64:
929ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
930ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Iop_Shl32: case Iop_Shl16: case Iop_Shl8:
931ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
932ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Iop_Shr8:
933ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               addInstr(env, AMD64Instr_Alu64R(
934ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                Aalu_AND, AMD64RMI_Imm(0xFF), dst));
935ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
936ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Iop_Shr16:
937ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               addInstr(env, AMD64Instr_Alu64R(
938ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                Aalu_AND, AMD64RMI_Imm(0xFFFF), dst));
939ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
940ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Iop_Shr32:
941ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               addInstr(env, AMD64Instr_MovxLQ(False, dst, dst));
942ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
943ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Iop_Sar8:
944ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               addInstr(env, AMD64Instr_Sh64(Ash_SHL, 56, dst));
945ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               addInstr(env, AMD64Instr_Sh64(Ash_SAR, 56, dst));
946ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
947ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Iop_Sar16:
948ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               addInstr(env, AMD64Instr_Sh64(Ash_SHL, 48, dst));
949ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               addInstr(env, AMD64Instr_Sh64(Ash_SAR, 48, dst));
950ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
951ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Iop_Sar32:
952ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               addInstr(env, AMD64Instr_MovxLQ(True, dst, dst));
953ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
954ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            default:
955ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               ppIROp(e->Iex.Binop.op);
956ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               vassert(0);
957ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
958ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
959ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Now consider the shift amount.  If it's a literal, we
960ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            can do a much better job than the general case. */
961ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (e->Iex.Binop.arg2->tag == Iex_Const) {
962ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* assert that the IR is well-typed */
963ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            Int nshift;
964ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vassert(e->Iex.Binop.arg2->Iex.Const.con->tag == Ico_U8);
965ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            nshift = e->Iex.Binop.arg2->Iex.Const.con->Ico.U8;
966ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vassert(nshift >= 0);
967ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (nshift > 0)
968ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               /* Can't allow nshift==0 since that means %cl */
969ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               addInstr(env, AMD64Instr_Sh64(shOp, nshift, dst));
970ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
971ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* General case; we have to force the amount into %cl. */
972ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg regR = iselIntExpr_R(env, e->Iex.Binop.arg2);
973ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, mk_iMOVsd_RR(regR,hregAMD64_RCX()));
974ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, AMD64Instr_Sh64(shOp, 0/* %cl */, dst));
975ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
976ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return dst;
977ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
978ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
979ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Deal with 64-bit SIMD binary ops */
980ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      second_is_UInt = False;
981ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch (e->Iex.Binop.op) {
982ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_Add8x8:
983ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            fn = (HWord)h_generic_calc_Add8x8; break;
984ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_Add16x4:
985ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            fn = (HWord)h_generic_calc_Add16x4; break;
986ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_Add32x2:
987ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            fn = (HWord)h_generic_calc_Add32x2; break;
988ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
989ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_Avg8Ux8:
990ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            fn = (HWord)h_generic_calc_Avg8Ux8; break;
991ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_Avg16Ux4:
992ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            fn = (HWord)h_generic_calc_Avg16Ux4; break;
993ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
994ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_CmpEQ8x8:
995ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            fn = (HWord)h_generic_calc_CmpEQ8x8; break;
996ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_CmpEQ16x4:
997ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            fn = (HWord)h_generic_calc_CmpEQ16x4; break;
998ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_CmpEQ32x2:
999ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            fn = (HWord)h_generic_calc_CmpEQ32x2; break;
1000ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1001ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_CmpGT8Sx8:
1002ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            fn = (HWord)h_generic_calc_CmpGT8Sx8; break;
1003ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_CmpGT16Sx4:
1004ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            fn = (HWord)h_generic_calc_CmpGT16Sx4; break;
1005ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_CmpGT32Sx2:
1006ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            fn = (HWord)h_generic_calc_CmpGT32Sx2; break;
1007ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1008ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_InterleaveHI8x8:
1009ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            fn = (HWord)h_generic_calc_InterleaveHI8x8; break;
1010ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_InterleaveLO8x8:
1011ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            fn = (HWord)h_generic_calc_InterleaveLO8x8; break;
1012ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_InterleaveHI16x4:
1013ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            fn = (HWord)h_generic_calc_InterleaveHI16x4; break;
1014ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_InterleaveLO16x4:
1015ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            fn = (HWord)h_generic_calc_InterleaveLO16x4; break;
1016ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_InterleaveHI32x2:
1017ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            fn = (HWord)h_generic_calc_InterleaveHI32x2; break;
1018ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_InterleaveLO32x2:
1019ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            fn = (HWord)h_generic_calc_InterleaveLO32x2; break;
1020ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_CatOddLanes16x4:
1021ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            fn = (HWord)h_generic_calc_CatOddLanes16x4; break;
1022ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_CatEvenLanes16x4:
1023ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            fn = (HWord)h_generic_calc_CatEvenLanes16x4; break;
1024ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_Perm8x8:
1025ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            fn = (HWord)h_generic_calc_Perm8x8; break;
1026ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1027ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_Max8Ux8:
1028ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            fn = (HWord)h_generic_calc_Max8Ux8; break;
1029ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_Max16Sx4:
1030ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            fn = (HWord)h_generic_calc_Max16Sx4; break;
1031ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_Min8Ux8:
1032ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            fn = (HWord)h_generic_calc_Min8Ux8; break;
1033ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_Min16Sx4:
1034ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            fn = (HWord)h_generic_calc_Min16Sx4; break;
1035ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1036ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_Mul16x4:
1037ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            fn = (HWord)h_generic_calc_Mul16x4; break;
1038ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_Mul32x2:
1039ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            fn = (HWord)h_generic_calc_Mul32x2; break;
1040ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_MulHi16Sx4:
1041ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            fn = (HWord)h_generic_calc_MulHi16Sx4; break;
1042ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_MulHi16Ux4:
1043ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            fn = (HWord)h_generic_calc_MulHi16Ux4; break;
1044ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1045ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_QAdd8Sx8:
1046ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            fn = (HWord)h_generic_calc_QAdd8Sx8; break;
1047ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_QAdd16Sx4:
1048ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            fn = (HWord)h_generic_calc_QAdd16Sx4; break;
1049ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_QAdd8Ux8:
1050ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            fn = (HWord)h_generic_calc_QAdd8Ux8; break;
1051ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_QAdd16Ux4:
1052ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            fn = (HWord)h_generic_calc_QAdd16Ux4; break;
1053ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1054b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         case Iop_QNarrowBin32Sto16Sx4:
1055b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            fn = (HWord)h_generic_calc_QNarrowBin32Sto16Sx4; break;
1056b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         case Iop_QNarrowBin16Sto8Sx8:
1057b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            fn = (HWord)h_generic_calc_QNarrowBin16Sto8Sx8; break;
1058b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         case Iop_QNarrowBin16Sto8Ux8:
1059b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            fn = (HWord)h_generic_calc_QNarrowBin16Sto8Ux8; break;
1060b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         case Iop_NarrowBin16to8x8:
1061b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            fn = (HWord)h_generic_calc_NarrowBin16to8x8; break;
1062b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         case Iop_NarrowBin32to16x4:
1063b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            fn = (HWord)h_generic_calc_NarrowBin32to16x4; break;
1064ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1065ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_QSub8Sx8:
1066ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            fn = (HWord)h_generic_calc_QSub8Sx8; break;
1067ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_QSub16Sx4:
1068ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            fn = (HWord)h_generic_calc_QSub16Sx4; break;
1069ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_QSub8Ux8:
1070ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            fn = (HWord)h_generic_calc_QSub8Ux8; break;
1071ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_QSub16Ux4:
1072ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            fn = (HWord)h_generic_calc_QSub16Ux4; break;
1073ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1074ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_Sub8x8:
1075ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            fn = (HWord)h_generic_calc_Sub8x8; break;
1076ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_Sub16x4:
1077ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            fn = (HWord)h_generic_calc_Sub16x4; break;
1078ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_Sub32x2:
1079ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            fn = (HWord)h_generic_calc_Sub32x2; break;
1080ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1081ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_ShlN32x2:
1082ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            fn = (HWord)h_generic_calc_ShlN32x2;
1083ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            second_is_UInt = True;
1084ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
1085ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_ShlN16x4:
1086ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            fn = (HWord)h_generic_calc_ShlN16x4;
1087ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            second_is_UInt = True;
1088ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
1089ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_ShlN8x8:
1090ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            fn = (HWord)h_generic_calc_ShlN8x8;
1091ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            second_is_UInt = True;
1092ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
1093ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_ShrN32x2:
1094ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            fn = (HWord)h_generic_calc_ShrN32x2;
1095ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            second_is_UInt = True;
1096ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
1097ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_ShrN16x4:
1098ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            fn = (HWord)h_generic_calc_ShrN16x4;
1099ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            second_is_UInt = True;
1100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
1101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_SarN32x2:
1102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            fn = (HWord)h_generic_calc_SarN32x2;
1103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            second_is_UInt = True;
1104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
1105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_SarN16x4:
1106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            fn = (HWord)h_generic_calc_SarN16x4;
1107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            second_is_UInt = True;
1108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
1109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_SarN8x8:
1110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            fn = (HWord)h_generic_calc_SarN8x8;
1111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            second_is_UInt = True;
1112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
1113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         default:
1115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            fn = (HWord)0; break;
1116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (fn != (HWord)0) {
1118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Note: the following assumes all helpers are of signature
1119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               ULong fn ( ULong, ULong ), and they are
1120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            not marked as regparm functions.
1121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         */
1122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg dst  = newVRegI(env);
1123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg argL = iselIntExpr_R(env, e->Iex.Binop.arg1);
1124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg argR = iselIntExpr_R(env, e->Iex.Binop.arg2);
1125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (second_is_UInt)
1126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, AMD64Instr_MovxLQ(False, argR, argR));
1127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, mk_iMOVsd_RR(argL, hregAMD64_RDI()) );
1128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, mk_iMOVsd_RR(argR, hregAMD64_RSI()) );
1129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, AMD64Instr_Call( Acc_ALWAYS, (ULong)fn, 2 ));
1130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, mk_iMOVsd_RR(hregAMD64_RAX(), dst));
1131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return dst;
1132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Handle misc other ops. */
1135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (e->Iex.Binop.op == Iop_Max32U) {
1137b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         HReg src1 = iselIntExpr_R(env, e->Iex.Binop.arg1);
1138b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         HReg dst  = newVRegI(env);
1139b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         HReg src2 = iselIntExpr_R(env, e->Iex.Binop.arg2);
1140b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         addInstr(env, mk_iMOVsd_RR(src1, dst));
1141b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         addInstr(env, AMD64Instr_Alu32R(Aalu_CMP, AMD64RMI_Reg(src2), dst));
1142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, AMD64Instr_CMov64(Acc_B, AMD64RM_Reg(src2), dst));
1143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return dst;
1144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (e->Iex.Binop.op == Iop_DivModS64to32
1147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          || e->Iex.Binop.op == Iop_DivModU64to32) {
1148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* 64 x 32 -> (32(rem),32(div)) division */
1149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Get the 64-bit operand into edx:eax, and the other into
1150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            any old R/M. */
1151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg      rax     = hregAMD64_RAX();
1152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg      rdx     = hregAMD64_RDX();
1153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg      dst     = newVRegI(env);
1154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         Bool      syned   = toBool(e->Iex.Binop.op == Iop_DivModS64to32);
1155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         AMD64RM*  rmRight = iselIntExpr_RM(env, e->Iex.Binop.arg2);
1156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Compute the left operand into a reg, and then
1157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            put the top half in edx and the bottom in eax. */
1158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg left64 = iselIntExpr_R(env, e->Iex.Binop.arg1);
1159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, mk_iMOVsd_RR(left64, rdx));
1160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, mk_iMOVsd_RR(left64, rax));
1161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, AMD64Instr_Sh64(Ash_SHR, 32, rdx));
1162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, AMD64Instr_Div(syned, 4, rmRight));
1163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 addInstr(env, AMD64Instr_MovxLQ(False, rdx, rdx));
1164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 addInstr(env, AMD64Instr_MovxLQ(False, rax, rax));
1165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, AMD64Instr_Sh64(Ash_SHL, 32, rdx));
1166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, mk_iMOVsd_RR(rax, dst));
1167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, AMD64Instr_Alu64R(Aalu_OR, AMD64RMI_Reg(rdx), dst));
1168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return dst;
1169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (e->Iex.Binop.op == Iop_32HLto64) {
1172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg hi32  = newVRegI(env);
1173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg lo32  = newVRegI(env);
1174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg hi32s = iselIntExpr_R(env, e->Iex.Binop.arg1);
1175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg lo32s = iselIntExpr_R(env, e->Iex.Binop.arg2);
1176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, mk_iMOVsd_RR(hi32s, hi32));
1177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, mk_iMOVsd_RR(lo32s, lo32));
1178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, AMD64Instr_Sh64(Ash_SHL, 32, hi32));
1179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 addInstr(env, AMD64Instr_MovxLQ(False, lo32, lo32));
1180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, AMD64Instr_Alu64R(
1181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          Aalu_OR, AMD64RMI_Reg(lo32), hi32));
1182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return hi32;
1183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (e->Iex.Binop.op == Iop_16HLto32) {
1186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg hi16  = newVRegI(env);
1187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg lo16  = newVRegI(env);
1188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg hi16s = iselIntExpr_R(env, e->Iex.Binop.arg1);
1189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg lo16s = iselIntExpr_R(env, e->Iex.Binop.arg2);
1190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, mk_iMOVsd_RR(hi16s, hi16));
1191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, mk_iMOVsd_RR(lo16s, lo16));
1192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, AMD64Instr_Sh64(Ash_SHL, 16, hi16));
1193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, AMD64Instr_Alu64R(
1194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          Aalu_AND, AMD64RMI_Imm(0xFFFF), lo16));
1195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, AMD64Instr_Alu64R(
1196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          Aalu_OR, AMD64RMI_Reg(lo16), hi16));
1197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return hi16;
1198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (e->Iex.Binop.op == Iop_8HLto16) {
1201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg hi8  = newVRegI(env);
1202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg lo8  = newVRegI(env);
1203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg hi8s = iselIntExpr_R(env, e->Iex.Binop.arg1);
1204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg lo8s = iselIntExpr_R(env, e->Iex.Binop.arg2);
1205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, mk_iMOVsd_RR(hi8s, hi8));
1206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, mk_iMOVsd_RR(lo8s, lo8));
1207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, AMD64Instr_Sh64(Ash_SHL, 8, hi8));
1208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, AMD64Instr_Alu64R(
1209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          Aalu_AND, AMD64RMI_Imm(0xFF), lo8));
1210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, AMD64Instr_Alu64R(
1211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          Aalu_OR, AMD64RMI_Reg(lo8), hi8));
1212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return hi8;
1213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (e->Iex.Binop.op == Iop_MullS32
1216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          || e->Iex.Binop.op == Iop_MullS16
1217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          || e->Iex.Binop.op == Iop_MullS8
1218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          || e->Iex.Binop.op == Iop_MullU32
1219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          || e->Iex.Binop.op == Iop_MullU16
1220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          || e->Iex.Binop.op == Iop_MullU8) {
1221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg a32   = newVRegI(env);
1222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg b32   = newVRegI(env);
1223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg a32s  = iselIntExpr_R(env, e->Iex.Binop.arg1);
1224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg b32s  = iselIntExpr_R(env, e->Iex.Binop.arg2);
1225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         Int          shift  = 0;
1226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         AMD64ShiftOp shr_op = Ash_SHR;
1227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         switch (e->Iex.Binop.op) {
1228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Iop_MullS32: shr_op = Ash_SAR; shift = 32; break;
1229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Iop_MullS16: shr_op = Ash_SAR; shift = 48; break;
1230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Iop_MullS8:  shr_op = Ash_SAR; shift = 56; break;
1231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Iop_MullU32: shr_op = Ash_SHR; shift = 32; break;
1232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Iop_MullU16: shr_op = Ash_SHR; shift = 48; break;
1233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Iop_MullU8:  shr_op = Ash_SHR; shift = 56; break;
1234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            default: vassert(0);
1235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
1236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, mk_iMOVsd_RR(a32s, a32));
1238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, mk_iMOVsd_RR(b32s, b32));
1239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, AMD64Instr_Sh64(Ash_SHL, shift, a32));
1240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, AMD64Instr_Sh64(Ash_SHL, shift, b32));
1241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, AMD64Instr_Sh64(shr_op,  shift, a32));
1242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, AMD64Instr_Sh64(shr_op,  shift, b32));
1243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, AMD64Instr_Alu64R(Aalu_MUL, AMD64RMI_Reg(a32), b32));
1244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return b32;
1245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (e->Iex.Binop.op == Iop_CmpF64) {
1248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg fL = iselDblExpr(env, e->Iex.Binop.arg1);
1249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg fR = iselDblExpr(env, e->Iex.Binop.arg2);
1250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg dst = newVRegI(env);
1251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, AMD64Instr_SseUComIS(8,fL,fR,dst));
1252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Mask out irrelevant parts of the result so as to conform
1253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            to the CmpF64 definition. */
1254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, AMD64Instr_Alu64R(Aalu_AND, AMD64RMI_Imm(0x45), dst));
1255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return dst;
1256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (e->Iex.Binop.op == Iop_F64toI32S
1259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          || e->Iex.Binop.op == Iop_F64toI64S) {
1260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         Int  szD = e->Iex.Binop.op==Iop_F64toI32S ? 4 : 8;
1261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg rf  = iselDblExpr(env, e->Iex.Binop.arg2);
1262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg dst = newVRegI(env);
1263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         set_SSE_rounding_mode( env, e->Iex.Binop.arg1 );
1264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, AMD64Instr_SseSF2SI( 8, szD, rf, dst ));
1265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         set_SSE_rounding_default(env);
1266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return dst;
1267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
1270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* --------- UNARY OP --------- */
1273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Iex_Unop: {
1274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* 1Uto8(64to1(expr64)) */
1276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      {
1277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DEFINE_PATTERN( p_1Uto8_64to1,
1278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         unop(Iop_1Uto8, unop(Iop_64to1, bind(0))) );
1279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (matchIRExpr(&mi,p_1Uto8_64to1,e)) {
1280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            IRExpr* expr64 = mi.bindee[0];
1281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg    dst    = newVRegI(env);
1282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg    src    = iselIntExpr_R(env, expr64);
1283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, mk_iMOVsd_RR(src,dst) );
1284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, AMD64Instr_Alu64R(Aalu_AND,
1285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                            AMD64RMI_Imm(1), dst));
1286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return dst;
1287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
1288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* 8Uto64(LDle(expr64)) */
1291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      {
1292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DEFINE_PATTERN(p_LDle8_then_8Uto64,
1293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        unop(Iop_8Uto64,
1294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             IRExpr_Load(Iend_LE,Ity_I8,bind(0))) );
1295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (matchIRExpr(&mi,p_LDle8_then_8Uto64,e)) {
1296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg dst = newVRegI(env);
1297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            AMD64AMode* amode = iselIntExpr_AMode ( env, mi.bindee[0] );
1298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, AMD64Instr_LoadEX(1,False,amode,dst));
1299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return dst;
1300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
1301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* 16Uto64(LDle(expr64)) */
1304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      {
1305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DEFINE_PATTERN(p_LDle16_then_16Uto64,
1306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        unop(Iop_16Uto64,
1307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             IRExpr_Load(Iend_LE,Ity_I16,bind(0))) );
1308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (matchIRExpr(&mi,p_LDle16_then_16Uto64,e)) {
1309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg dst = newVRegI(env);
1310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            AMD64AMode* amode = iselIntExpr_AMode ( env, mi.bindee[0] );
1311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, AMD64Instr_LoadEX(2,False,amode,dst));
1312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return dst;
1313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
1314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1316b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      /* 32Uto64( Add32/Sub32/And32/Or32/Xor32(expr32, expr32) )
1317b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         Use 32 bit arithmetic and let the default zero-extend rule
1318b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         do the 32Uto64 for free. */
1319b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      if (e->Iex.Unop.op == Iop_32Uto64 && e->Iex.Unop.arg->tag == Iex_Binop) {
1320b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         IROp    opi  = e->Iex.Unop.arg->Iex.Binop.op; /* inner op */
1321b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         IRExpr* argL = e->Iex.Unop.arg->Iex.Binop.arg1;
1322b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         IRExpr* argR = e->Iex.Unop.arg->Iex.Binop.arg2;
1323b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         AMD64AluOp aluOp = Aalu_INVALID;
1324b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         switch (opi) {
1325b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            case Iop_Add32: aluOp = Aalu_ADD; break;
1326b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            case Iop_Sub32: aluOp = Aalu_SUB; break;
1327b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            case Iop_And32: aluOp = Aalu_AND; break;
1328b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            case Iop_Or32:  aluOp = Aalu_OR;  break;
1329b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            case Iop_Xor32: aluOp = Aalu_XOR; break;
1330b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            default: break;
1331b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         }
1332b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         if (aluOp != Aalu_INVALID) {
1333b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            /* For commutative ops we assume any literal values are on
1334b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               the second operand. */
1335b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            HReg dst      = newVRegI(env);
1336b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            HReg reg      = iselIntExpr_R(env, argL);
1337b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            AMD64RMI* rmi = iselIntExpr_RMI(env, argR);
1338b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            addInstr(env, mk_iMOVsd_RR(reg,dst));
1339b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            addInstr(env, AMD64Instr_Alu32R(aluOp, rmi, dst));
1340b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            return dst;
1341b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         }
1342b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         /* just fall through to normal handling for Iop_32Uto64 */
1343b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      }
1344b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1345b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      /* Fallback cases */
1346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch (e->Iex.Unop.op) {
1347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_32Uto64:
1348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_32Sto64: {
1349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg dst = newVRegI(env);
1350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg src = iselIntExpr_R(env, e->Iex.Unop.arg);
1351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, AMD64Instr_MovxLQ(e->Iex.Unop.op == Iop_32Sto64,
1352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                            src, dst) );
1353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return dst;
1354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
1355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_128HIto64: {
1356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg rHi, rLo;
1357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            iselInt128Expr(&rHi,&rLo, env, e->Iex.Unop.arg);
1358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return rHi; /* and abandon rLo */
1359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
1360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_128to64: {
1361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg rHi, rLo;
1362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            iselInt128Expr(&rHi,&rLo, env, e->Iex.Unop.arg);
1363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return rLo; /* and abandon rHi */
1364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
1365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_8Uto16:
1366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_8Uto32:
1367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_8Uto64:
1368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_16Uto64:
1369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_16Uto32: {
1370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg dst     = newVRegI(env);
1371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg src     = iselIntExpr_R(env, e->Iex.Unop.arg);
1372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            Bool srcIs16 = toBool( e->Iex.Unop.op==Iop_16Uto32
1373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                   || e->Iex.Unop.op==Iop_16Uto64 );
1374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            UInt mask    = srcIs16 ? 0xFFFF : 0xFF;
1375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, mk_iMOVsd_RR(src,dst) );
1376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, AMD64Instr_Alu64R(Aalu_AND,
1377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                            AMD64RMI_Imm(mask), dst));
1378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return dst;
1379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
1380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_8Sto16:
1381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_8Sto64:
1382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_8Sto32:
1383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_16Sto32:
1384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_16Sto64: {
1385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg dst     = newVRegI(env);
1386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg src     = iselIntExpr_R(env, e->Iex.Unop.arg);
1387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            Bool srcIs16 = toBool( e->Iex.Unop.op==Iop_16Sto32
1388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                   || e->Iex.Unop.op==Iop_16Sto64 );
1389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            UInt amt     = srcIs16 ? 48 : 56;
1390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, mk_iMOVsd_RR(src,dst) );
1391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, AMD64Instr_Sh64(Ash_SHL, amt, dst));
1392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, AMD64Instr_Sh64(Ash_SAR, amt, dst));
1393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return dst;
1394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
1395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 	 case Iop_Not8:
1396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 	 case Iop_Not16:
1397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_Not32:
1398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_Not64: {
1399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg dst = newVRegI(env);
1400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg src = iselIntExpr_R(env, e->Iex.Unop.arg);
1401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, mk_iMOVsd_RR(src,dst) );
1402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, AMD64Instr_Unary64(Aun_NOT,dst));
1403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return dst;
1404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
1405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_16HIto8:
1406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_32HIto16:
1407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_64HIto32: {
1408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg dst  = newVRegI(env);
1409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg src  = iselIntExpr_R(env, e->Iex.Unop.arg);
1410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            Int shift = 0;
1411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            switch (e->Iex.Unop.op) {
1412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               case Iop_16HIto8:  shift = 8;  break;
1413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               case Iop_32HIto16: shift = 16; break;
1414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               case Iop_64HIto32: shift = 32; break;
1415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               default: vassert(0);
1416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
1417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, mk_iMOVsd_RR(src,dst) );
1418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, AMD64Instr_Sh64(Ash_SHR, shift, dst));
1419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return dst;
1420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
1421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_1Uto64:
1422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_1Uto32:
1423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_1Uto8: {
1424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg dst           = newVRegI(env);
1425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            AMD64CondCode cond = iselCondCode(env, e->Iex.Unop.arg);
1426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, AMD64Instr_Set64(cond,dst));
1427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return dst;
1428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
1429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_1Sto8:
1430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_1Sto16:
1431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_1Sto32:
1432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_1Sto64: {
1433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* could do better than this, but for now ... */
1434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg dst           = newVRegI(env);
1435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            AMD64CondCode cond = iselCondCode(env, e->Iex.Unop.arg);
1436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, AMD64Instr_Set64(cond,dst));
1437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, AMD64Instr_Sh64(Ash_SHL, 63, dst));
1438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, AMD64Instr_Sh64(Ash_SAR, 63, dst));
1439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return dst;
1440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
1441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_Ctz64: {
1442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* Count trailing zeroes, implemented by amd64 'bsfq' */
1443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg dst = newVRegI(env);
1444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg src = iselIntExpr_R(env, e->Iex.Unop.arg);
1445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, AMD64Instr_Bsfr64(True,src,dst));
1446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return dst;
1447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
1448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_Clz64: {
1449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* Count leading zeroes.  Do 'bsrq' to establish the index
1450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               of the highest set bit, and subtract that value from
1451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               63. */
1452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg tmp = newVRegI(env);
1453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg dst = newVRegI(env);
1454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg src = iselIntExpr_R(env, e->Iex.Unop.arg);
1455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, AMD64Instr_Bsfr64(False,src,tmp));
1456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, AMD64Instr_Alu64R(Aalu_MOV,
1457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                            AMD64RMI_Imm(63), dst));
1458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, AMD64Instr_Alu64R(Aalu_SUB,
1459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                            AMD64RMI_Reg(tmp), dst));
1460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return dst;
1461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
1462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_CmpwNEZ64: {
1464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg dst = newVRegI(env);
1465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg src = iselIntExpr_R(env, e->Iex.Unop.arg);
1466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, mk_iMOVsd_RR(src,dst));
1467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, AMD64Instr_Unary64(Aun_NEG,dst));
1468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, AMD64Instr_Alu64R(Aalu_OR,
1469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                            AMD64RMI_Reg(src), dst));
1470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, AMD64Instr_Sh64(Ash_SAR, 63, dst));
1471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return dst;
1472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
1473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_CmpwNEZ32: {
1475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg src = newVRegI(env);
1476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg dst = newVRegI(env);
1477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg pre = iselIntExpr_R(env, e->Iex.Unop.arg);
1478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, mk_iMOVsd_RR(pre,src));
1479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, AMD64Instr_MovxLQ(False, src, src));
1480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, mk_iMOVsd_RR(src,dst));
1481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, AMD64Instr_Unary64(Aun_NEG,dst));
1482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, AMD64Instr_Alu64R(Aalu_OR,
1483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                            AMD64RMI_Reg(src), dst));
1484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, AMD64Instr_Sh64(Ash_SAR, 63, dst));
1485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return dst;
1486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
1487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_Left8:
1489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_Left16:
1490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_Left32:
1491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_Left64: {
1492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg dst = newVRegI(env);
1493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg src = iselIntExpr_R(env, e->Iex.Unop.arg);
1494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, mk_iMOVsd_RR(src, dst));
1495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, AMD64Instr_Unary64(Aun_NEG, dst));
1496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, AMD64Instr_Alu64R(Aalu_OR, AMD64RMI_Reg(src), dst));
1497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return dst;
1498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
1499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_V128to32: {
1501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg        dst     = newVRegI(env);
1502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg        vec     = iselVecExpr(env, e->Iex.Unop.arg);
1503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            AMD64AMode* rsp_m16 = AMD64AMode_IR(-16, hregAMD64_RSP());
1504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, AMD64Instr_SseLdSt(False/*store*/, 16, vec, rsp_m16));
1505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, AMD64Instr_LoadEX(4, False/*z-widen*/, rsp_m16, dst));
1506ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return dst;
1507ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
1508ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* V128{HI}to64 */
1510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_V128HIto64:
1511ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_V128to64: {
1512ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg dst = newVRegI(env);
1513663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            Int  off = e->Iex.Unop.op==Iop_V128HIto64 ? -8 : -16;
1514663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            HReg rsp = hregAMD64_RSP();
1515ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg vec = iselVecExpr(env, e->Iex.Unop.arg);
1516663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            AMD64AMode* m16_rsp = AMD64AMode_IR(-16, rsp);
1517663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            AMD64AMode* off_rsp = AMD64AMode_IR(off, rsp);
1518663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addInstr(env, AMD64Instr_SseLdSt(False/*store*/,
1519663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                             16, vec, m16_rsp));
1520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, AMD64Instr_Alu64R( Aalu_MOV,
1521663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                             AMD64RMI_Mem(off_rsp), dst ));
1522663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            return dst;
1523663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
1524663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
1525663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case Iop_V256to64_0: case Iop_V256to64_1:
1526663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case Iop_V256to64_2: case Iop_V256to64_3: {
1527663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            HReg vHi, vLo, vec;
1528663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            iselDVecExpr(&vHi, &vLo, env, e->Iex.Unop.arg);
1529663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            /* Do the first part of the selection by deciding which of
1530663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               the 128 bit registers do look at, and second part using
1531663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               the same scheme as for V128{HI}to64 above. */
1532663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            Int off = 0;
1533663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            switch (e->Iex.Unop.op) {
1534663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               case Iop_V256to64_0: vec = vLo; off = -16; break;
1535663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               case Iop_V256to64_1: vec = vLo; off =  -8; break;
1536663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               case Iop_V256to64_2: vec = vHi; off = -16; break;
1537663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               case Iop_V256to64_3: vec = vHi; off =  -8; break;
1538663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               default: vassert(0);
1539663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            }
1540663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            HReg        dst     = newVRegI(env);
1541663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            HReg        rsp     = hregAMD64_RSP();
1542663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            AMD64AMode* m16_rsp = AMD64AMode_IR(-16, rsp);
1543663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            AMD64AMode* off_rsp = AMD64AMode_IR(off, rsp);
1544663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addInstr(env, AMD64Instr_SseLdSt(False/*store*/,
1545663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                             16, vec, m16_rsp));
1546663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addInstr(env, AMD64Instr_Alu64R( Aalu_MOV,
1547663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                             AMD64RMI_Mem(off_rsp), dst ));
1548ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return dst;
1549ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
1550ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1551ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* ReinterpF64asI64(e) */
1552ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Given an IEEE754 double, produce an I64 with the same bit
1553ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            pattern. */
1554ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_ReinterpF64asI64: {
1555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            AMD64AMode* m8_rsp = AMD64AMode_IR(-8, hregAMD64_RSP());
1556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg        dst    = newVRegI(env);
1557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg        src    = iselDblExpr(env, e->Iex.Unop.arg);
1558ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* paranoia */
1559ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            set_SSE_rounding_default(env);
1560ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, AMD64Instr_SseLdSt(False/*store*/, 8, src, m8_rsp));
1561ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, AMD64Instr_Alu64R(
1562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             Aalu_MOV, AMD64RMI_Mem(m8_rsp), dst));
1563ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return dst;
1564ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
1565ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1566ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* ReinterpF32asI32(e) */
1567ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Given an IEEE754 single, produce an I64 with the same bit
1568ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            pattern in the lower half. */
1569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_ReinterpF32asI32: {
1570ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            AMD64AMode* m8_rsp = AMD64AMode_IR(-8, hregAMD64_RSP());
1571ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg        dst    = newVRegI(env);
1572ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg        src    = iselFltExpr(env, e->Iex.Unop.arg);
1573ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* paranoia */
1574ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            set_SSE_rounding_default(env);
1575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, AMD64Instr_SseLdSt(False/*store*/, 4, src, m8_rsp));
1576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, AMD64Instr_LoadEX(4, False/*unsigned*/, m8_rsp, dst ));
1577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return dst;
1578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
1579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_16to8:
1581ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_32to8:
1582ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_64to8:
1583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_32to16:
1584ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_64to16:
1585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_64to32:
1586ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* These are no-ops. */
1587ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return iselIntExpr_R(env, e->Iex.Unop.arg);
1588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         default:
1590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
1591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Deal with unary 64-bit SIMD ops. */
1594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch (e->Iex.Unop.op) {
1595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_CmpNEZ32x2:
1596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            fn = (HWord)h_generic_calc_CmpNEZ32x2; break;
1597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_CmpNEZ16x4:
1598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            fn = (HWord)h_generic_calc_CmpNEZ16x4; break;
1599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_CmpNEZ8x8:
1600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            fn = (HWord)h_generic_calc_CmpNEZ8x8; break;
1601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         default:
1602ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            fn = (HWord)0; break;
1603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (fn != (HWord)0) {
1605ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Note: the following assumes all helpers are of
1606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            signature
1607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               ULong fn ( ULong ), and they are
1608ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            not marked as regparm functions.
1609ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         */
1610ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg dst = newVRegI(env);
1611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg arg = iselIntExpr_R(env, e->Iex.Unop.arg);
1612ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, mk_iMOVsd_RR(arg, hregAMD64_RDI()) );
1613ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, AMD64Instr_Call( Acc_ALWAYS, (ULong)fn, 1 ));
1614ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, mk_iMOVsd_RR(hregAMD64_RAX(), dst));
1615ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return dst;
1616ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1617ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1618ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
1619ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1620ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1621ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* --------- GET --------- */
1622ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Iex_Get: {
1623ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (ty == Ity_I64) {
1624ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg dst = newVRegI(env);
1625ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, AMD64Instr_Alu64R(
1626ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          Aalu_MOV,
1627ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          AMD64RMI_Mem(
1628ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             AMD64AMode_IR(e->Iex.Get.offset,
1629ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                           hregAMD64_RBP())),
1630ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          dst));
1631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return dst;
1632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1633ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (ty == Ity_I8 || ty == Ity_I16 || ty == Ity_I32) {
1634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg dst = newVRegI(env);
1635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, AMD64Instr_LoadEX(
1636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          toUChar(ty==Ity_I8 ? 1 : (ty==Ity_I16 ? 2 : 4)),
1637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          False,
1638ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          AMD64AMode_IR(e->Iex.Get.offset,hregAMD64_RBP()),
1639ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          dst));
1640ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return dst;
1641ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1642ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
1643ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1644ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1645ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Iex_GetI: {
1646ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      AMD64AMode* am
1647ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         = genGuestArrayOffset(
1648ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              env, e->Iex.GetI.descr,
1649ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   e->Iex.GetI.ix, e->Iex.GetI.bias );
1650ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HReg dst = newVRegI(env);
1651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (ty == Ity_I8) {
1652ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, AMD64Instr_LoadEX( 1, False, am, dst ));
1653ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return dst;
1654ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1655ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (ty == Ity_I64) {
1656ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, AMD64Instr_Alu64R( Aalu_MOV, AMD64RMI_Mem(am), dst ));
1657ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return dst;
1658ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1659ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
1660ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1661ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1662ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* --------- CCALL --------- */
1663ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Iex_CCall: {
1664ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HReg    dst = newVRegI(env);
1665ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert(ty == e->Iex.CCall.retty);
1666ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1667ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* be very restrictive for now.  Only 64-bit ints allowed
1668ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         for args, and 64 or 32 bits for return type. */
1669ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (e->Iex.CCall.retty != Ity_I64 && e->Iex.CCall.retty != Ity_I32)
1670ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto irreducible;
1671ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1672ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Marshal args, do the call. */
1673ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      doHelperCall( env, False, NULL, e->Iex.CCall.cee, e->Iex.CCall.args );
1674ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1675ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Move to dst, and zero out the top 32 bits if the result type is
1676ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         Ity_I32.  Probably overkill, but still .. */
1677ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (e->Iex.CCall.retty == Ity_I64)
1678ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, mk_iMOVsd_RR(hregAMD64_RAX(), dst));
1679ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      else
1680ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, AMD64Instr_MovxLQ(False, hregAMD64_RAX(), dst));
1681ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1682ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return dst;
1683ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1684ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1685ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* --------- LITERAL --------- */
1686ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* 64/32/16/8-bit literals */
1687ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Iex_Const:
1688ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (ty == Ity_I64) {
1689ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg r = newVRegI(env);
1690ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, AMD64Instr_Imm64(e->Iex.Const.con->Ico.U64, r));
1691ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return r;
1692ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else {
1693ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         AMD64RMI* rmi = iselIntExpr_RMI ( env, e );
1694ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg      r   = newVRegI(env);
1695ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, AMD64Instr_Alu64R(Aalu_MOV, rmi, r));
1696ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return r;
1697ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1698ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1699ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* --------- MULTIPLEX --------- */
1700ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Iex_Mux0X: {
1701ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     if ((ty == Ity_I64 || ty == Ity_I32 || ty == Ity_I16 || ty == Ity_I8)
1702ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         && typeOfIRExpr(env->type_env,e->Iex.Mux0X.cond) == Ity_I8) {
1703ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        HReg     r8;
1704ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        HReg     rX  = iselIntExpr_R(env, e->Iex.Mux0X.exprX);
1705ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        AMD64RM* r0  = iselIntExpr_RM(env, e->Iex.Mux0X.expr0);
1706ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        HReg dst = newVRegI(env);
1707ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        addInstr(env, mk_iMOVsd_RR(rX,dst));
1708ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        r8 = iselIntExpr_R(env, e->Iex.Mux0X.cond);
1709ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        addInstr(env, AMD64Instr_Test64(0xFF, r8));
1710ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        addInstr(env, AMD64Instr_CMov64(Acc_Z,r0,dst));
1711ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        return dst;
1712ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1713ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
1714ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1715ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1716ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* --------- TERNARY OP --------- */
1717ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Iex_Triop: {
1718663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      IRTriop *triop = e->Iex.Triop.details;
1719ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* C3210 flags following FPU partial remainder (fprem), both
1720ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IEEE compliant (PREM1) and non-IEEE compliant (PREM). */
1721663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (triop->op == Iop_PRemC3210F64
1722663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          || triop->op == Iop_PRem1C3210F64) {
1723ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         AMD64AMode* m8_rsp = AMD64AMode_IR(-8, hregAMD64_RSP());
1724663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         HReg        arg1   = iselDblExpr(env, triop->arg2);
1725663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         HReg        arg2   = iselDblExpr(env, triop->arg3);
1726ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg        dst    = newVRegI(env);
1727ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, AMD64Instr_A87Free(2));
1728ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1729ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* one arg -> top of x87 stack */
1730ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, AMD64Instr_SseLdSt(False/*store*/, 8, arg2, m8_rsp));
1731ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, AMD64Instr_A87PushPop(m8_rsp, True/*push*/, 8));
1732ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1733ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* other arg -> top of x87 stack */
1734ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, AMD64Instr_SseLdSt(False/*store*/, 8, arg1, m8_rsp));
1735ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, AMD64Instr_A87PushPop(m8_rsp, True/*push*/, 8));
1736ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1737663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         switch (triop->op) {
1738ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Iop_PRemC3210F64:
1739ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               addInstr(env, AMD64Instr_A87FpOp(Afp_PREM));
1740ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
1741ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Iop_PRem1C3210F64:
1742ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               addInstr(env, AMD64Instr_A87FpOp(Afp_PREM1));
1743ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
1744ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            default:
1745ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               vassert(0);
1746ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
1747ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Ignore the result, and instead make off with the FPU's
1748ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    C3210 flags (in the status word). */
1749ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, AMD64Instr_A87StSW(m8_rsp));
1750ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, AMD64Instr_Alu64R(Aalu_MOV,AMD64RMI_Mem(m8_rsp),dst));
1751ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, AMD64Instr_Alu64R(Aalu_AND,AMD64RMI_Imm(0x4700),dst));
1752ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return dst;
1753ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1754ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
1755ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1756ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1757ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   default:
1758ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   break;
1759ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } /* switch (e->tag) */
1760ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1761ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* We get here if no pattern matched. */
1762ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  irreducible:
1763ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ppIRExpr(e);
1764ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vpanic("iselIntExpr_R(amd64): cannot reduce tree");
1765ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1766ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1767ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1768ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------*/
1769ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- ISEL: Integer expression auxiliaries              ---*/
1770ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------*/
1771ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1772ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* --------------------- AMODEs --------------------- */
1773ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1774ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Return an AMode which computes the value of the specified
1775ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   expression, possibly also adding insns to the code list as a
1776ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   result.  The expression may only be a 32-bit one.
1777ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
1778ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1779ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic AMD64AMode* iselIntExpr_AMode ( ISelEnv* env, IRExpr* e )
1780ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1781ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   AMD64AMode* am = iselIntExpr_AMode_wrk(env, e);
1782ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(sane_AMode(am));
1783ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return am;
1784ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1785ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1786ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* DO NOT CALL THIS DIRECTLY ! */
1787ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic AMD64AMode* iselIntExpr_AMode_wrk ( ISelEnv* env, IRExpr* e )
1788ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1789ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   MatchInfo mi;
1790ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   DECLARE_PATTERN(p_complex);
1791ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRType ty = typeOfIRExpr(env->type_env,e);
1792ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(ty == Ity_I64);
1793ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1794ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Add64( Add64(expr1, Shl64(expr2, imm8)), simm32 ) */
1795ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /*              bind0        bind1  bind2   bind3   */
1796ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   DEFINE_PATTERN(p_complex,
1797ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      binop( Iop_Add64,
1798ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             binop( Iop_Add64,
1799ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    bind(0),
1800ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    binop(Iop_Shl64, bind(1), bind(2))
1801ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  ),
1802ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             bind(3)
1803ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           )
1804ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   );
1805ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (matchIRExpr(&mi, p_complex, e)) {
1806ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRExpr* expr1  = mi.bindee[0];
1807ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRExpr* expr2  = mi.bindee[1];
1808ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRExpr* imm8   = mi.bindee[2];
1809ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRExpr* simm32 = mi.bindee[3];
1810ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (imm8->tag == Iex_Const
1811ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          && imm8->Iex.Const.con->tag == Ico_U8
1812ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          && imm8->Iex.Const.con->Ico.U8 < 4
1813ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          /* imm8 is OK, now check simm32 */
1814ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          && simm32->tag == Iex_Const
1815ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          && simm32->Iex.Const.con->tag == Ico_U64
1816ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          && fitsIn32Bits(simm32->Iex.Const.con->Ico.U64)) {
1817ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         UInt shift = imm8->Iex.Const.con->Ico.U8;
1818ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         UInt offset = toUInt(simm32->Iex.Const.con->Ico.U64);
1819ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg r1 = iselIntExpr_R(env, expr1);
1820ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg r2 = iselIntExpr_R(env, expr2);
1821ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(shift == 0 || shift == 1 || shift == 2 || shift == 3);
1822ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return AMD64AMode_IRRS(offset, r1, r2, shift);
1823ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1824ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1825ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1826ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Add64(expr1, Shl64(expr2, imm)) */
1827ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_Binop
1828ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && e->Iex.Binop.op == Iop_Add64
1829ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && e->Iex.Binop.arg2->tag == Iex_Binop
1830ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && e->Iex.Binop.arg2->Iex.Binop.op == Iop_Shl64
1831ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && e->Iex.Binop.arg2->Iex.Binop.arg2->tag == Iex_Const
1832ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && e->Iex.Binop.arg2->Iex.Binop.arg2->Iex.Const.con->tag == Ico_U8) {
1833ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt shift = e->Iex.Binop.arg2->Iex.Binop.arg2->Iex.Const.con->Ico.U8;
1834ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (shift == 1 || shift == 2 || shift == 3) {
1835ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg r1 = iselIntExpr_R(env, e->Iex.Binop.arg1);
1836ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg r2 = iselIntExpr_R(env, e->Iex.Binop.arg2->Iex.Binop.arg1 );
1837ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return AMD64AMode_IRRS(0, r1, r2, shift);
1838ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1839ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1840ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1841ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Add64(expr,i) */
1842ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_Binop
1843ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && e->Iex.Binop.op == Iop_Add64
1844ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && e->Iex.Binop.arg2->tag == Iex_Const
1845ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && e->Iex.Binop.arg2->Iex.Const.con->tag == Ico_U64
1846ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && fitsIn32Bits(e->Iex.Binop.arg2->Iex.Const.con->Ico.U64)) {
1847ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HReg r1 = iselIntExpr_R(env, e->Iex.Binop.arg1);
1848ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return AMD64AMode_IR(
1849ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                toUInt(e->Iex.Binop.arg2->Iex.Const.con->Ico.U64),
1850ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                r1
1851ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             );
1852ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1853ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1854ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Doesn't match anything in particular.  Generate it into
1855ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      a register and use that. */
1856ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   {
1857ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HReg r1 = iselIntExpr_R(env, e);
1858ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return AMD64AMode_IR(0, r1);
1859ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1860ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1861ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1862ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1863ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* --------------------- RMIs --------------------- */
1864ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1865ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Similarly, calculate an expression into an X86RMI operand.  As with
1866ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   iselIntExpr_R, the expression can have type 32, 16 or 8 bits.  */
1867ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1868ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic AMD64RMI* iselIntExpr_RMI ( ISelEnv* env, IRExpr* e )
1869ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1870ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   AMD64RMI* rmi = iselIntExpr_RMI_wrk(env, e);
1871ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* sanity checks ... */
1872ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (rmi->tag) {
1873ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Armi_Imm:
1874ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return rmi;
1875ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Armi_Reg:
1876ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(hregClass(rmi->Armi.Reg.reg) == HRcInt64);
1877ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(hregIsVirtual(rmi->Armi.Reg.reg));
1878ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return rmi;
1879ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Armi_Mem:
1880ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(sane_AMode(rmi->Armi.Mem.am));
1881ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return rmi;
1882ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
1883ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vpanic("iselIntExpr_RMI: unknown amd64 RMI tag");
1884ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1885ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1886ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1887ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* DO NOT CALL THIS DIRECTLY ! */
1888ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic AMD64RMI* iselIntExpr_RMI_wrk ( ISelEnv* env, IRExpr* e )
1889ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1890ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRType ty = typeOfIRExpr(env->type_env,e);
1891ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(ty == Ity_I64 || ty == Ity_I32
1892ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           || ty == Ity_I16 || ty == Ity_I8);
1893ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1894ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* special case: immediate 64/32/16/8 */
1895ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_Const) {
1896ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch (e->Iex.Const.con->tag) {
1897ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case Ico_U64:
1898ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           if (fitsIn32Bits(e->Iex.Const.con->Ico.U64)) {
1899ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              return AMD64RMI_Imm(toUInt(e->Iex.Const.con->Ico.U64));
1900ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           }
1901ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           break;
1902ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Ico_U32:
1903ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return AMD64RMI_Imm(e->Iex.Const.con->Ico.U32); break;
1904ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Ico_U16:
1905ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return AMD64RMI_Imm(0xFFFF & e->Iex.Const.con->Ico.U16); break;
1906ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Ico_U8:
1907ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return AMD64RMI_Imm(0xFF & e->Iex.Const.con->Ico.U8); break;
1908ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         default:
1909ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vpanic("iselIntExpr_RMI.Iex_Const(amd64)");
1910ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1911ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1912ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1913ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* special case: 64-bit GET */
1914ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_Get && ty == Ity_I64) {
1915ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return AMD64RMI_Mem(AMD64AMode_IR(e->Iex.Get.offset,
1916ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                        hregAMD64_RBP()));
1917ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1918ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1919ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* special case: 64-bit load from memory */
1920ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_Load && ty == Ity_I64
1921ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && e->Iex.Load.end == Iend_LE) {
1922ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      AMD64AMode* am = iselIntExpr_AMode(env, e->Iex.Load.addr);
1923ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return AMD64RMI_Mem(am);
1924ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1925ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1926ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* default case: calculate into a register and return that */
1927ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   {
1928ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HReg r = iselIntExpr_R ( env, e );
1929ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return AMD64RMI_Reg(r);
1930ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1931ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1932ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1933ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1934ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* --------------------- RIs --------------------- */
1935ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1936ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Calculate an expression into an AMD64RI operand.  As with
1937ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   iselIntExpr_R, the expression can have type 64, 32, 16 or 8
1938ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   bits. */
1939ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1940ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic AMD64RI* iselIntExpr_RI ( ISelEnv* env, IRExpr* e )
1941ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1942ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   AMD64RI* ri = iselIntExpr_RI_wrk(env, e);
1943ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* sanity checks ... */
1944ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (ri->tag) {
1945ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ari_Imm:
1946ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return ri;
1947ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ari_Reg:
1948ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(hregClass(ri->Ari.Reg.reg) == HRcInt64);
1949ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(hregIsVirtual(ri->Ari.Reg.reg));
1950ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return ri;
1951ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
1952ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vpanic("iselIntExpr_RI: unknown amd64 RI tag");
1953ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1954ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1955ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1956ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* DO NOT CALL THIS DIRECTLY ! */
1957ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic AMD64RI* iselIntExpr_RI_wrk ( ISelEnv* env, IRExpr* e )
1958ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1959ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRType ty = typeOfIRExpr(env->type_env,e);
1960ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(ty == Ity_I64 || ty == Ity_I32
1961ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           || ty == Ity_I16 || ty == Ity_I8);
1962ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1963ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* special case: immediate */
1964ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_Const) {
1965ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch (e->Iex.Const.con->tag) {
1966ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case Ico_U64:
1967ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           if (fitsIn32Bits(e->Iex.Const.con->Ico.U64)) {
1968ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              return AMD64RI_Imm(toUInt(e->Iex.Const.con->Ico.U64));
1969ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           }
1970ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           break;
1971ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Ico_U32:
1972ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return AMD64RI_Imm(e->Iex.Const.con->Ico.U32);
1973ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Ico_U16:
1974ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return AMD64RI_Imm(0xFFFF & e->Iex.Const.con->Ico.U16);
1975ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Ico_U8:
1976ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return AMD64RI_Imm(0xFF & e->Iex.Const.con->Ico.U8);
1977ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         default:
1978ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vpanic("iselIntExpr_RMI.Iex_Const(amd64)");
1979ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1980ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1981ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1982ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* default case: calculate into a register and return that */
1983ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   {
1984ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HReg r = iselIntExpr_R ( env, e );
1985ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return AMD64RI_Reg(r);
1986ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1987ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1988ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1989ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1990ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* --------------------- RMs --------------------- */
1991ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1992ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Similarly, calculate an expression into an AMD64RM operand.  As
1993ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   with iselIntExpr_R, the expression can have type 64, 32, 16 or 8
1994ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   bits.  */
1995ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1996ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic AMD64RM* iselIntExpr_RM ( ISelEnv* env, IRExpr* e )
1997ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1998ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   AMD64RM* rm = iselIntExpr_RM_wrk(env, e);
1999ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* sanity checks ... */
2000ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (rm->tag) {
2001ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Arm_Reg:
2002ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(hregClass(rm->Arm.Reg.reg) == HRcInt64);
2003ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(hregIsVirtual(rm->Arm.Reg.reg));
2004ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return rm;
2005ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Arm_Mem:
2006ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(sane_AMode(rm->Arm.Mem.am));
2007ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return rm;
2008ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
2009ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vpanic("iselIntExpr_RM: unknown amd64 RM tag");
2010ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2011ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2012ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2013ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* DO NOT CALL THIS DIRECTLY ! */
2014ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic AMD64RM* iselIntExpr_RM_wrk ( ISelEnv* env, IRExpr* e )
2015ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2016ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRType ty = typeOfIRExpr(env->type_env,e);
2017ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(ty == Ity_I64 || ty == Ity_I32 || ty == Ity_I16 || ty == Ity_I8);
2018ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2019ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* special case: 64-bit GET */
2020ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_Get && ty == Ity_I64) {
2021ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return AMD64RM_Mem(AMD64AMode_IR(e->Iex.Get.offset,
2022ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                       hregAMD64_RBP()));
2023ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2024ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2025ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* special case: load from memory */
2026ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2027ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* default case: calculate into a register and return that */
2028ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   {
2029ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HReg r = iselIntExpr_R ( env, e );
2030ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return AMD64RM_Reg(r);
2031ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2032ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2033ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2034ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2035ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* --------------------- CONDCODE --------------------- */
2036ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2037ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Generate code to evaluated a bit-typed expression, returning the
2038ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   condition code which would correspond when the expression would
2039ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   notionally have returned 1. */
2040ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2041ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic AMD64CondCode iselCondCode ( ISelEnv* env, IRExpr* e )
2042ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2043ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Uh, there's nothing we can sanity check here, unfortunately. */
2044ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return iselCondCode_wrk(env,e);
2045ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2046ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2047ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* DO NOT CALL THIS DIRECTLY ! */
2048ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic AMD64CondCode iselCondCode_wrk ( ISelEnv* env, IRExpr* e )
2049ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2050ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   MatchInfo mi;
2051ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2052ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(e);
2053ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(typeOfIRExpr(env->type_env,e) == Ity_I1);
2054ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2055ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* var */
2056ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_RdTmp) {
2057ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HReg r64 = lookupIRTemp(env, e->Iex.RdTmp.tmp);
2058ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HReg dst = newVRegI(env);
2059ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env, mk_iMOVsd_RR(r64,dst));
2060ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env, AMD64Instr_Alu64R(Aalu_AND,AMD64RMI_Imm(1),dst));
2061ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return Acc_NZ;
2062ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2063ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2064ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Constant 1:Bit */
2065ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_Const) {
2066ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HReg r;
2067ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert(e->Iex.Const.con->tag == Ico_U1);
2068ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert(e->Iex.Const.con->Ico.U1 == True
2069ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              || e->Iex.Const.con->Ico.U1 == False);
2070ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      r = newVRegI(env);
2071ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env, AMD64Instr_Alu64R(Aalu_MOV,AMD64RMI_Imm(0),r));
2072ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env, AMD64Instr_Alu64R(Aalu_XOR,AMD64RMI_Reg(r),r));
2073ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return e->Iex.Const.con->Ico.U1 ? Acc_Z : Acc_NZ;
2074ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2075ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2076ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Not1(...) */
2077ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_Unop && e->Iex.Unop.op == Iop_Not1) {
2078ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Generate code for the arg, and negate the test condition */
2079ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return 1 ^ iselCondCode(env, e->Iex.Unop.arg);
2080ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2081ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2082ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* --- patterns rooted at: 64to1 --- */
2083ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2084ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* 64to1 */
2085ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_Unop && e->Iex.Unop.op == Iop_64to1) {
2086ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HReg reg = iselIntExpr_R(env, e->Iex.Unop.arg);
2087ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env, AMD64Instr_Test64(1,reg));
2088ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return Acc_NZ;
2089ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2090ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2091663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* --- patterns rooted at: 32to1 --- */
2092663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
2093663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* 32to1 */
2094663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (e->tag == Iex_Unop && e->Iex.Unop.op == Iop_32to1) {
2095663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      HReg reg = iselIntExpr_R(env, e->Iex.Unop.arg);
2096663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      addInstr(env, AMD64Instr_Test64(1,reg));
2097663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      return Acc_NZ;
2098663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
2099663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
2100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* --- patterns rooted at: CmpNEZ8 --- */
2101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* CmpNEZ8(x) */
2103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_Unop
2104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && e->Iex.Unop.op == Iop_CmpNEZ8) {
2105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HReg r = iselIntExpr_R(env, e->Iex.Unop.arg);
2106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env, AMD64Instr_Test64(0xFF,r));
2107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return Acc_NZ;
2108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* --- patterns rooted at: CmpNEZ16 --- */
2111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* CmpNEZ16(x) */
2113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_Unop
2114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && e->Iex.Unop.op == Iop_CmpNEZ16) {
2115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HReg r = iselIntExpr_R(env, e->Iex.Unop.arg);
2116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env, AMD64Instr_Test64(0xFFFF,r));
2117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return Acc_NZ;
2118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* --- patterns rooted at: CmpNEZ32 --- */
2121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* CmpNEZ32(x) */
2123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_Unop
2124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && e->Iex.Unop.op == Iop_CmpNEZ32) {
2125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HReg      r1   = iselIntExpr_R(env, e->Iex.Unop.arg);
2126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      AMD64RMI* rmi2 = AMD64RMI_Imm(0);
2127b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      addInstr(env, AMD64Instr_Alu32R(Aalu_CMP,rmi2,r1));
2128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return Acc_NZ;
2129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* --- patterns rooted at: CmpNEZ64 --- */
2132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* CmpNEZ64(Or64(x,y)) */
2134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   {
2135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DECLARE_PATTERN(p_CmpNEZ64_Or64);
2136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DEFINE_PATTERN(p_CmpNEZ64_Or64,
2137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     unop(Iop_CmpNEZ64, binop(Iop_Or64, bind(0), bind(1))));
2138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (matchIRExpr(&mi, p_CmpNEZ64_Or64, e)) {
2139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg      r0   = iselIntExpr_R(env, mi.bindee[0]);
2140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         AMD64RMI* rmi1 = iselIntExpr_RMI(env, mi.bindee[1]);
2141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg      tmp  = newVRegI(env);
2142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, mk_iMOVsd_RR(r0, tmp));
2143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, AMD64Instr_Alu64R(Aalu_OR,rmi1,tmp));
2144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return Acc_NZ;
2145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* CmpNEZ64(x) */
2149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_Unop
2150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && e->Iex.Unop.op == Iop_CmpNEZ64) {
2151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HReg      r1   = iselIntExpr_R(env, e->Iex.Unop.arg);
2152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      AMD64RMI* rmi2 = AMD64RMI_Imm(0);
2153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env, AMD64Instr_Alu64R(Aalu_CMP,rmi2,r1));
2154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return Acc_NZ;
2155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* --- patterns rooted at: Cmp{EQ,NE}{8,16,32} --- */
2158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* CmpEQ8 / CmpNE8 */
2160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_Binop
2161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && (e->Iex.Binop.op == Iop_CmpEQ8
2162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           || e->Iex.Binop.op == Iop_CmpNE8
2163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           || e->Iex.Binop.op == Iop_CasCmpEQ8
2164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           || e->Iex.Binop.op == Iop_CasCmpNE8)) {
2165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HReg      r1   = iselIntExpr_R(env, e->Iex.Binop.arg1);
2166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      AMD64RMI* rmi2 = iselIntExpr_RMI(env, e->Iex.Binop.arg2);
2167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HReg      r    = newVRegI(env);
2168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env, mk_iMOVsd_RR(r1,r));
2169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env, AMD64Instr_Alu64R(Aalu_XOR,rmi2,r));
2170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env, AMD64Instr_Alu64R(Aalu_AND,AMD64RMI_Imm(0xFF),r));
2171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch (e->Iex.Binop.op) {
2172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_CmpEQ8: case Iop_CasCmpEQ8: return Acc_Z;
2173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_CmpNE8: case Iop_CasCmpNE8: return Acc_NZ;
2174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         default: vpanic("iselCondCode(amd64): CmpXX8");
2175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* CmpEQ16 / CmpNE16 */
2179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_Binop
2180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && (e->Iex.Binop.op == Iop_CmpEQ16
2181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           || e->Iex.Binop.op == Iop_CmpNE16
2182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           || e->Iex.Binop.op == Iop_CasCmpEQ16
2183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           || e->Iex.Binop.op == Iop_CasCmpNE16)) {
2184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HReg      r1   = iselIntExpr_R(env, e->Iex.Binop.arg1);
2185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      AMD64RMI* rmi2 = iselIntExpr_RMI(env, e->Iex.Binop.arg2);
2186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HReg      r    = newVRegI(env);
2187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env, mk_iMOVsd_RR(r1,r));
2188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env, AMD64Instr_Alu64R(Aalu_XOR,rmi2,r));
2189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env, AMD64Instr_Alu64R(Aalu_AND,AMD64RMI_Imm(0xFFFF),r));
2190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch (e->Iex.Binop.op) {
2191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_CmpEQ16: case Iop_CasCmpEQ16: return Acc_Z;
2192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_CmpNE16: case Iop_CasCmpNE16: return Acc_NZ;
2193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         default: vpanic("iselCondCode(amd64): CmpXX16");
2194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2197b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   /* CmpNE64(ccall, 64-bit constant) (--smc-check=all optimisation).
2198b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      Saves a "movq %rax, %tmp" compared to the default route. */
2199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_Binop
2200b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov       && e->Iex.Binop.op == Iop_CmpNE64
2201b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov       && e->Iex.Binop.arg1->tag == Iex_CCall
2202b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov       && e->Iex.Binop.arg2->tag == Iex_Const) {
2203b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      IRExpr* cal = e->Iex.Binop.arg1;
2204b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      IRExpr* con = e->Iex.Binop.arg2;
2205b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      HReg    tmp = newVRegI(env);
2206b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      /* clone & partial-eval of generic Iex_CCall and Iex_Const cases */
2207b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      vassert(cal->Iex.CCall.retty == Ity_I64); /* else ill-typed IR */
2208b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      vassert(con->Iex.Const.con->tag == Ico_U64);
2209b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      /* Marshal args, do the call. */
2210b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      doHelperCall( env, False, NULL, cal->Iex.CCall.cee, cal->Iex.CCall.args );
2211b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      addInstr(env, AMD64Instr_Imm64(con->Iex.Const.con->Ico.U64, tmp));
2212b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      addInstr(env, AMD64Instr_Alu64R(Aalu_CMP,
2213b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                      AMD64RMI_Reg(hregAMD64_RAX()), tmp));
2214b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      return Acc_NZ;
2215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Cmp*64*(x,y) */
2218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_Binop
2219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && (e->Iex.Binop.op == Iop_CmpEQ64
2220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           || e->Iex.Binop.op == Iop_CmpNE64
2221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           || e->Iex.Binop.op == Iop_CmpLT64S
2222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           || e->Iex.Binop.op == Iop_CmpLT64U
2223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           || e->Iex.Binop.op == Iop_CmpLE64S
2224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           || e->Iex.Binop.op == Iop_CmpLE64U
2225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           || e->Iex.Binop.op == Iop_CasCmpEQ64
2226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           || e->Iex.Binop.op == Iop_CasCmpNE64)) {
2227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HReg      r1   = iselIntExpr_R(env, e->Iex.Binop.arg1);
2228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      AMD64RMI* rmi2 = iselIntExpr_RMI(env, e->Iex.Binop.arg2);
2229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env, AMD64Instr_Alu64R(Aalu_CMP,rmi2,r1));
2230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch (e->Iex.Binop.op) {
2231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_CmpEQ64: case Iop_CasCmpEQ64: return Acc_Z;
2232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_CmpNE64: case Iop_CasCmpNE64: return Acc_NZ;
2233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 case Iop_CmpLT64S: return Acc_L;
2234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 case Iop_CmpLT64U: return Acc_B;
2235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 case Iop_CmpLE64S: return Acc_LE;
2236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_CmpLE64U: return Acc_BE;
2237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         default: vpanic("iselCondCode(amd64): CmpXX64");
2238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2241b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   /* Cmp*32*(x,y) */
2242b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   if (e->tag == Iex_Binop
2243b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov       && (e->Iex.Binop.op == Iop_CmpEQ32
2244b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov           || e->Iex.Binop.op == Iop_CmpNE32
2245b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov           || e->Iex.Binop.op == Iop_CmpLT32S
2246b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov           || e->Iex.Binop.op == Iop_CmpLT32U
2247b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov           || e->Iex.Binop.op == Iop_CmpLE32S
2248b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov           || e->Iex.Binop.op == Iop_CmpLE32U
2249b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov           || e->Iex.Binop.op == Iop_CasCmpEQ32
2250b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov           || e->Iex.Binop.op == Iop_CasCmpNE32)) {
2251b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      HReg      r1   = iselIntExpr_R(env, e->Iex.Binop.arg1);
2252b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      AMD64RMI* rmi2 = iselIntExpr_RMI(env, e->Iex.Binop.arg2);
2253b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      addInstr(env, AMD64Instr_Alu32R(Aalu_CMP,rmi2,r1));
2254b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      switch (e->Iex.Binop.op) {
2255b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         case Iop_CmpEQ32: case Iop_CasCmpEQ32: return Acc_Z;
2256b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         case Iop_CmpNE32: case Iop_CasCmpNE32: return Acc_NZ;
2257b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov	 case Iop_CmpLT32S: return Acc_L;
2258b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov	 case Iop_CmpLT32U: return Acc_B;
2259b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov	 case Iop_CmpLE32S: return Acc_LE;
2260b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         case Iop_CmpLE32U: return Acc_BE;
2261b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         default: vpanic("iselCondCode(amd64): CmpXX32");
2262b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      }
2263b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   }
2264b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
2265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ppIRExpr(e);
2266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vpanic("iselCondCode(amd64)");
2267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------*/
2271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- ISEL: Integer expressions (128 bit)               ---*/
2272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------*/
2273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Compute a 128-bit value into a register pair, which is returned as
2275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   the first two parameters.  As with iselIntExpr_R, these may be
2276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   either real or virtual regs; in any case they must not be changed
2277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   by subsequent code emitted by the caller.  */
2278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void iselInt128Expr ( HReg* rHi, HReg* rLo,
2280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             ISelEnv* env, IRExpr* e )
2281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   iselInt128Expr_wrk(rHi, rLo, env, e);
2283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  if 0
2284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vex_printf("\n"); ppIRExpr(e); vex_printf("\n");
2285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  endif
2286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(hregClass(*rHi) == HRcInt64);
2287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(hregIsVirtual(*rHi));
2288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(hregClass(*rLo) == HRcInt64);
2289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(hregIsVirtual(*rLo));
2290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* DO NOT CALL THIS DIRECTLY ! */
2293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void iselInt128Expr_wrk ( HReg* rHi, HReg* rLo,
2294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                 ISelEnv* env, IRExpr* e )
2295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(e);
2297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(typeOfIRExpr(env->type_env,e) == Ity_I128);
2298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* read 128-bit IRTemp */
2300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_RdTmp) {
2301663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      lookupIRTempPair( rHi, rLo, env, e->Iex.RdTmp.tmp);
2302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return;
2303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* --------- BINARY ops --------- */
2306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_Binop) {
2307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch (e->Iex.Binop.op) {
2308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* 64 x 64 -> 128 multiply */
2309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_MullU64:
2310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_MullS64: {
2311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* get one operand into %rax, and the other into a R/M.
2312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               Need to make an educated guess about which is better in
2313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               which. */
2314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg     tLo    = newVRegI(env);
2315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg     tHi    = newVRegI(env);
2316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            Bool     syned  = toBool(e->Iex.Binop.op == Iop_MullS64);
2317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            AMD64RM* rmLeft = iselIntExpr_RM(env, e->Iex.Binop.arg1);
2318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg     rRight = iselIntExpr_R(env, e->Iex.Binop.arg2);
2319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, mk_iMOVsd_RR(rRight, hregAMD64_RAX()));
2320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, AMD64Instr_MulL(syned, rmLeft));
2321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* Result is now in RDX:RAX.  Tell the caller. */
2322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, mk_iMOVsd_RR(hregAMD64_RDX(), tHi));
2323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, mk_iMOVsd_RR(hregAMD64_RAX(), tLo));
2324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            *rHi = tHi;
2325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            *rLo = tLo;
2326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return;
2327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
2328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* 128 x 64 -> (64(rem),64(div)) division */
2330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_DivModU128to64:
2331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_DivModS128to64: {
2332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* Get the 128-bit operand into rdx:rax, and the other into
2333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               any old R/M. */
2334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg sHi, sLo;
2335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg     tLo     = newVRegI(env);
2336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg     tHi     = newVRegI(env);
2337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            Bool     syned   = toBool(e->Iex.Binop.op == Iop_DivModS128to64);
2338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            AMD64RM* rmRight = iselIntExpr_RM(env, e->Iex.Binop.arg2);
2339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            iselInt128Expr(&sHi,&sLo, env, e->Iex.Binop.arg1);
2340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, mk_iMOVsd_RR(sHi, hregAMD64_RDX()));
2341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, mk_iMOVsd_RR(sLo, hregAMD64_RAX()));
2342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, AMD64Instr_Div(syned, 8, rmRight));
2343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, mk_iMOVsd_RR(hregAMD64_RDX(), tHi));
2344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, mk_iMOVsd_RR(hregAMD64_RAX(), tLo));
2345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            *rHi = tHi;
2346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            *rLo = tLo;
2347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return;
2348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
2349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* 64HLto128(e1,e2) */
2351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_64HLto128:
2352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            *rHi = iselIntExpr_R(env, e->Iex.Binop.arg1);
2353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            *rLo = iselIntExpr_R(env, e->Iex.Binop.arg2);
2354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return;
2355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         default:
2357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
2358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } /* if (e->tag == Iex_Binop) */
2360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ppIRExpr(e);
2362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vpanic("iselInt128Expr");
2363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------*/
2367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- ISEL: Floating point expressions (32 bit)         ---*/
2368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------*/
2369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Nothing interesting here; really just wrappers for
2371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   64-bit stuff. */
2372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic HReg iselFltExpr ( ISelEnv* env, IRExpr* e )
2374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   HReg r = iselFltExpr_wrk( env, e );
2376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  if 0
2377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vex_printf("\n"); ppIRExpr(e); vex_printf("\n");
2378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  endif
2379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(hregClass(r) == HRcVec128);
2380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(hregIsVirtual(r));
2381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return r;
2382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* DO NOT CALL THIS DIRECTLY */
2385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic HReg iselFltExpr_wrk ( ISelEnv* env, IRExpr* e )
2386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRType ty = typeOfIRExpr(env->type_env,e);
2388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(ty == Ity_F32);
2389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_RdTmp) {
2391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return lookupIRTemp(env, e->Iex.RdTmp.tmp);
2392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_Load && e->Iex.Load.end == Iend_LE) {
2395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      AMD64AMode* am;
2396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HReg res = newVRegV(env);
2397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert(e->Iex.Load.ty == Ity_F32);
2398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      am = iselIntExpr_AMode(env, e->Iex.Load.addr);
2399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env, AMD64Instr_SseLdSt(True/*load*/, 4, res, am));
2400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return res;
2401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_Binop
2404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && e->Iex.Binop.op == Iop_F64toF32) {
2405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Although the result is still held in a standard SSE register,
2406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         we need to round it to reflect the loss of accuracy/range
2407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         entailed in casting it to a 32-bit float. */
2408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HReg dst = newVRegV(env);
2409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HReg src = iselDblExpr(env, e->Iex.Binop.arg2);
2410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      set_SSE_rounding_mode( env, e->Iex.Binop.arg1 );
2411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env, AMD64Instr_SseSDSS(True/*D->S*/,src,dst));
2412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      set_SSE_rounding_default( env );
2413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return dst;
2414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_Get) {
2417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      AMD64AMode* am = AMD64AMode_IR( e->Iex.Get.offset,
2418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                       hregAMD64_RBP() );
2419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HReg res = newVRegV(env);
2420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env, AMD64Instr_SseLdSt( True/*load*/, 4, res, am ));
2421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return res;
2422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_Unop
2425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && e->Iex.Unop.op == Iop_ReinterpI32asF32) {
2426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       /* Given an I32, produce an IEEE754 float with the same bit
2427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          pattern. */
2428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       HReg        dst    = newVRegV(env);
2429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       HReg        src    = iselIntExpr_R(env, e->Iex.Unop.arg);
2430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       AMD64AMode* m4_rsp = AMD64AMode_IR(-4, hregAMD64_RSP());
2431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       addInstr(env, AMD64Instr_Store(4, src, m4_rsp));
2432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       addInstr(env, AMD64Instr_SseLdSt( True/*load*/, 4, dst, m4_rsp ));
2433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       return dst;
2434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_Binop && e->Iex.Binop.op == Iop_RoundF32toInt) {
2437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      AMD64AMode* m8_rsp = AMD64AMode_IR(-8, hregAMD64_RSP());
2438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HReg        arg    = iselFltExpr(env, e->Iex.Binop.arg2);
2439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HReg        dst    = newVRegV(env);
2440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* rf now holds the value to be rounded.  The first thing to do
2442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         is set the FPU's rounding mode accordingly. */
2443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Set host x87 rounding mode */
2445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      set_FPU_rounding_mode( env, e->Iex.Binop.arg1 );
2446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env, AMD64Instr_SseLdSt(False/*store*/, 4, arg, m8_rsp));
2448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env, AMD64Instr_A87Free(1));
2449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env, AMD64Instr_A87PushPop(m8_rsp, True/*push*/, 4));
2450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env, AMD64Instr_A87FpOp(Afp_ROUND));
2451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env, AMD64Instr_A87PushPop(m8_rsp, False/*pop*/, 4));
2452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env, AMD64Instr_SseLdSt(True/*load*/, 4, dst, m8_rsp));
2453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Restore default x87 rounding. */
2455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      set_FPU_rounding_default( env );
2456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return dst;
2458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ppIRExpr(e);
2461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vpanic("iselFltExpr_wrk");
2462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------*/
2466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- ISEL: Floating point expressions (64 bit)         ---*/
2467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------*/
2468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Compute a 64-bit floating point value into the lower half of an xmm
2470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   register, the identity of which is returned.  As with
2471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   iselIntExpr_R, the returned reg will be virtual, and it must not be
2472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   changed by subsequent code emitted by the caller.
2473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
2474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* IEEE 754 formats.  From http://www.freesoft.org/CIE/RFC/1832/32.htm:
2476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    Type                  S (1 bit)   E (11 bits)   F (52 bits)
2478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    ----                  ---------   -----------   -----------
2479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    signalling NaN        u           2047 (max)    .0uuuuu---u
2480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                                    (with at least
2481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                                     one 1 bit)
2482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    quiet NaN             u           2047 (max)    .1uuuuu---u
2483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    negative infinity     1           2047 (max)    .000000---0
2485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    positive infinity     0           2047 (max)    .000000---0
2487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    negative zero         1           0             .000000---0
2489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    positive zero         0           0             .000000---0
2491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
2492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic HReg iselDblExpr ( ISelEnv* env, IRExpr* e )
2494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   HReg r = iselDblExpr_wrk( env, e );
2496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  if 0
2497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vex_printf("\n"); ppIRExpr(e); vex_printf("\n");
2498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  endif
2499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(hregClass(r) == HRcVec128);
2500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(hregIsVirtual(r));
2501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return r;
2502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* DO NOT CALL THIS DIRECTLY */
2505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic HReg iselDblExpr_wrk ( ISelEnv* env, IRExpr* e )
2506ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2507ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRType ty = typeOfIRExpr(env->type_env,e);
2508ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(e);
2509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(ty == Ity_F64);
2510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2511ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_RdTmp) {
2512ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return lookupIRTemp(env, e->Iex.RdTmp.tmp);
2513ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2514ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2515ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_Const) {
2516ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      union { ULong u64; Double f64; } u;
2517ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HReg res = newVRegV(env);
2518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HReg tmp = newVRegI(env);
2519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert(sizeof(u) == 8);
2520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert(sizeof(u.u64) == 8);
2521ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert(sizeof(u.f64) == 8);
2522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2523ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (e->Iex.Const.con->tag == Ico_F64) {
2524ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         u.f64 = e->Iex.Const.con->Ico.F64;
2525ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2526ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      else if (e->Iex.Const.con->tag == Ico_F64i) {
2527ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         u.u64 = e->Iex.Const.con->Ico.F64i;
2528ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2529ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      else
2530ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vpanic("iselDblExpr(amd64): const");
2531ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2532ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env, AMD64Instr_Imm64(u.u64, tmp));
2533ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env, AMD64Instr_Push(AMD64RMI_Reg(tmp)));
2534ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env, AMD64Instr_SseLdSt(
2535ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       True/*load*/, 8, res,
2536ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       AMD64AMode_IR(0, hregAMD64_RSP())
2537ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              ));
2538ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      add_to_rsp(env, 8);
2539ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return res;
2540ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2541ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2542ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_Load && e->Iex.Load.end == Iend_LE) {
2543ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      AMD64AMode* am;
2544ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HReg res = newVRegV(env);
2545ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert(e->Iex.Load.ty == Ity_F64);
2546ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      am = iselIntExpr_AMode(env, e->Iex.Load.addr);
2547ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env, AMD64Instr_SseLdSt( True/*load*/, 8, res, am ));
2548ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return res;
2549ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2550ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2551ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_Get) {
2552ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      AMD64AMode* am = AMD64AMode_IR( e->Iex.Get.offset,
2553ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                      hregAMD64_RBP() );
2554ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HReg res = newVRegV(env);
2555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env, AMD64Instr_SseLdSt( True/*load*/, 8, res, am ));
2556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return res;
2557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2558ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2559ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_GetI) {
2560ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      AMD64AMode* am
2561ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         = genGuestArrayOffset(
2562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              env, e->Iex.GetI.descr,
2563ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   e->Iex.GetI.ix, e->Iex.GetI.bias );
2564ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HReg res = newVRegV(env);
2565ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env, AMD64Instr_SseLdSt( True/*load*/, 8, res, am ));
2566ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return res;
2567ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2568ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_Triop) {
2570663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      IRTriop *triop = e->Iex.Triop.details;
2571ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      AMD64SseOp op = Asse_INVALID;
2572663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      switch (triop->op) {
2573ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_AddF64: op = Asse_ADDF; break;
2574ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_SubF64: op = Asse_SUBF; break;
2575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_MulF64: op = Asse_MULF; break;
2576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_DivF64: op = Asse_DIVF; break;
2577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         default: break;
2578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (op != Asse_INVALID) {
2580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg dst  = newVRegV(env);
2581663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         HReg argL = iselDblExpr(env, triop->arg2);
2582663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         HReg argR = iselDblExpr(env, triop->arg3);
2583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, mk_vMOVsd_RR(argL, dst));
2584ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* XXXROUNDINGFIXME */
2585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* set roundingmode here */
2586ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, AMD64Instr_Sse64FLo(op, argR, dst));
2587ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return dst;
2588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_Binop && e->Iex.Binop.op == Iop_RoundF64toInt) {
2592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      AMD64AMode* m8_rsp = AMD64AMode_IR(-8, hregAMD64_RSP());
2593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HReg        arg    = iselDblExpr(env, e->Iex.Binop.arg2);
2594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HReg        dst    = newVRegV(env);
2595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* rf now holds the value to be rounded.  The first thing to do
2597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         is set the FPU's rounding mode accordingly. */
2598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Set host x87 rounding mode */
2600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      set_FPU_rounding_mode( env, e->Iex.Binop.arg1 );
2601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2602ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env, AMD64Instr_SseLdSt(False/*store*/, 8, arg, m8_rsp));
2603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env, AMD64Instr_A87Free(1));
2604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env, AMD64Instr_A87PushPop(m8_rsp, True/*push*/, 8));
2605ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env, AMD64Instr_A87FpOp(Afp_ROUND));
2606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env, AMD64Instr_A87PushPop(m8_rsp, False/*pop*/, 8));
2607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env, AMD64Instr_SseLdSt(True/*load*/, 8, dst, m8_rsp));
2608ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2609ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Restore default x87 rounding. */
2610ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      set_FPU_rounding_default( env );
2611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2612ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return dst;
2613ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2614ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2615663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTriop *triop = e->Iex.Triop.details;
2616ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_Triop
2617663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng       && (triop->op == Iop_ScaleF64
2618663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng           || triop->op == Iop_AtanF64
2619663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng           || triop->op == Iop_Yl2xF64
2620663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng           || triop->op == Iop_Yl2xp1F64
2621663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng           || triop->op == Iop_PRemF64
2622663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng           || triop->op == Iop_PRem1F64)
2623ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ) {
2624ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      AMD64AMode* m8_rsp = AMD64AMode_IR(-8, hregAMD64_RSP());
2625663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      HReg        arg1   = iselDblExpr(env, triop->arg2);
2626663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      HReg        arg2   = iselDblExpr(env, triop->arg3);
2627ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HReg        dst    = newVRegV(env);
2628663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      Bool     arg2first = toBool(triop->op == Iop_ScaleF64
2629663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                  || triop->op == Iop_PRemF64
2630663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                  || triop->op == Iop_PRem1F64);
2631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env, AMD64Instr_A87Free(2));
2632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2633ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* one arg -> top of x87 stack */
2634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env, AMD64Instr_SseLdSt(
2635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       False/*store*/, 8, arg2first ? arg2 : arg1, m8_rsp));
2636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env, AMD64Instr_A87PushPop(m8_rsp, True/*push*/, 8));
2637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2638ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* other arg -> top of x87 stack */
2639ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env, AMD64Instr_SseLdSt(
2640ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       False/*store*/, 8, arg2first ? arg1 : arg2, m8_rsp));
2641ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env, AMD64Instr_A87PushPop(m8_rsp, True/*push*/, 8));
2642ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2643ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* do it */
2644ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* XXXROUNDINGFIXME */
2645ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* set roundingmode here */
2646663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      switch (triop->op) {
2647ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_ScaleF64:
2648ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, AMD64Instr_A87FpOp(Afp_SCALE));
2649ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
2650ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_AtanF64:
2651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, AMD64Instr_A87FpOp(Afp_ATAN));
2652ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
2653ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_Yl2xF64:
2654ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, AMD64Instr_A87FpOp(Afp_YL2X));
2655ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
2656ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_Yl2xp1F64:
2657ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, AMD64Instr_A87FpOp(Afp_YL2XP1));
2658ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
2659ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_PRemF64:
2660ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, AMD64Instr_A87FpOp(Afp_PREM));
2661ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
2662ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_PRem1F64:
2663ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, AMD64Instr_A87FpOp(Afp_PREM1));
2664ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
2665ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         default:
2666ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vassert(0);
2667ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2668ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2669ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* save result */
2670ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env, AMD64Instr_A87PushPop(m8_rsp, False/*pop*/, 8));
2671ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env, AMD64Instr_SseLdSt(True/*load*/, 8, dst, m8_rsp));
2672ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return dst;
2673ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2674ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2675ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_Binop && e->Iex.Binop.op == Iop_I64StoF64) {
2676ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HReg dst = newVRegV(env);
2677ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HReg src = iselIntExpr_R(env, e->Iex.Binop.arg2);
2678ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      set_SSE_rounding_mode( env, e->Iex.Binop.arg1 );
2679ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env, AMD64Instr_SseSI2SF( 8, 8, src, dst ));
2680ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      set_SSE_rounding_default( env );
2681ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return dst;
2682ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2683ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2684ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_Unop && e->Iex.Unop.op == Iop_I32StoF64) {
2685ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HReg dst = newVRegV(env);
2686ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HReg src = iselIntExpr_R(env, e->Iex.Unop.arg);
2687ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      set_SSE_rounding_default( env );
2688ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env, AMD64Instr_SseSI2SF( 4, 8, src, dst ));
2689ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return dst;
2690ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2691ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2692ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_Unop
2693ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && (e->Iex.Unop.op == Iop_NegF64
2694ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           || e->Iex.Unop.op == Iop_AbsF64)) {
2695ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Sigh ... very rough code.  Could do much better. */
2696ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Get the 128-bit literal 00---0 10---0 into a register
2697ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         and xor/nand it with the value to be negated. */
2698ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HReg r1  = newVRegI(env);
2699ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HReg dst = newVRegV(env);
2700ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HReg tmp = newVRegV(env);
2701ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HReg src = iselDblExpr(env, e->Iex.Unop.arg);
2702ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      AMD64AMode* rsp0 = AMD64AMode_IR(0, hregAMD64_RSP());
2703ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env, mk_vMOVsd_RR(src,tmp));
2704ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env, AMD64Instr_Push(AMD64RMI_Imm(0)));
2705ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env, AMD64Instr_Imm64( 1ULL<<63, r1 ));
2706ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env, AMD64Instr_Push(AMD64RMI_Reg(r1)));
2707ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env, AMD64Instr_SseLdSt(True, 16, dst, rsp0));
2708ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2709ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (e->Iex.Unop.op == Iop_NegF64)
2710ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, AMD64Instr_SseReRg(Asse_XOR, tmp, dst));
2711ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      else
2712ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, AMD64Instr_SseReRg(Asse_ANDN, tmp, dst));
2713ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2714ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      add_to_rsp(env, 16);
2715ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return dst;
2716ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2717ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2718ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_Binop) {
2719ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      A87FpOp fpop = Afp_INVALID;
2720ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch (e->Iex.Binop.op) {
2721ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_SqrtF64: fpop = Afp_SQRT; break;
2722ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_SinF64:  fpop = Afp_SIN;  break;
2723ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_CosF64:  fpop = Afp_COS;  break;
2724ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_TanF64:  fpop = Afp_TAN;  break;
2725ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_2xm1F64: fpop = Afp_2XM1; break;
2726ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         default: break;
2727ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2728ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (fpop != Afp_INVALID) {
2729ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         AMD64AMode* m8_rsp = AMD64AMode_IR(-8, hregAMD64_RSP());
2730ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg        arg    = iselDblExpr(env, e->Iex.Binop.arg2);
2731ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg        dst    = newVRegV(env);
2732ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         Int     nNeeded    = e->Iex.Binop.op==Iop_TanF64 ? 2 : 1;
2733ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, AMD64Instr_SseLdSt(False/*store*/, 8, arg, m8_rsp));
2734ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, AMD64Instr_A87Free(nNeeded));
2735ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, AMD64Instr_A87PushPop(m8_rsp, True/*push*/, 8));
2736ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* XXXROUNDINGFIXME */
2737ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* set roundingmode here */
2738ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, AMD64Instr_A87FpOp(fpop));
2739ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (e->Iex.Binop.op==Iop_TanF64) {
2740ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* get rid of the extra 1.0 that fptan pushes */
2741ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, AMD64Instr_A87PushPop(m8_rsp, False/*pop*/, 8));
2742ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
2743ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, AMD64Instr_A87PushPop(m8_rsp, False/*pop*/, 8));
2744ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, AMD64Instr_SseLdSt(True/*load*/, 8, dst, m8_rsp));
2745ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return dst;
2746ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2747ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2748ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2749ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_Unop) {
2750ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch (e->Iex.Unop.op) {
2751ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//..          case Iop_I32toF64: {
2752ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//..             HReg dst = newVRegF(env);
2753ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//..             HReg ri  = iselIntExpr_R(env, e->Iex.Unop.arg);
2754ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//..             addInstr(env, X86Instr_Push(X86RMI_Reg(ri)));
2755ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//..             set_FPU_rounding_default(env);
2756ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//..             addInstr(env, X86Instr_FpLdStI(
2757ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//..                              True/*load*/, 4, dst,
2758ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//..                              X86AMode_IR(0, hregX86_ESP())));
2759ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//..             add_to_esp(env, 4);
2760ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//..             return dst;
2761ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//..          }
2762ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_ReinterpI64asF64: {
2763ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* Given an I64, produce an IEEE754 double with the same
2764ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               bit pattern. */
2765ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            AMD64AMode* m8_rsp = AMD64AMode_IR(-8, hregAMD64_RSP());
2766ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg        dst    = newVRegV(env);
2767ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            AMD64RI*    src    = iselIntExpr_RI(env, e->Iex.Unop.arg);
2768ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* paranoia */
2769ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            set_SSE_rounding_default(env);
2770ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, AMD64Instr_Alu64M(Aalu_MOV, src, m8_rsp));
2771ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, AMD64Instr_SseLdSt(True/*load*/, 8, dst, m8_rsp));
2772ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return dst;
2773ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
2774ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iop_F32toF64: {
2775ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg f32;
2776ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg f64 = newVRegV(env);
2777ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* this shouldn't be necessary, but be paranoid ... */
2778ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            set_SSE_rounding_default(env);
2779ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            f32 = iselFltExpr(env, e->Iex.Unop.arg);
2780ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, AMD64Instr_SseSDSS(False/*S->D*/, f32, f64));
2781ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return f64;
2782ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
2783ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         default:
2784ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
2785ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2786ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2787ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2788ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* --------- MULTIPLEX --------- */
2789ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_Mux0X) {
2790ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HReg r8, rX, r0, dst;
2791ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert(ty == Ity_F64);
2792ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert(typeOfIRExpr(env->type_env,e->Iex.Mux0X.cond) == Ity_I8);
2793ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      r8  = iselIntExpr_R(env, e->Iex.Mux0X.cond);
2794ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      rX  = iselDblExpr(env, e->Iex.Mux0X.exprX);
2795ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      r0  = iselDblExpr(env, e->Iex.Mux0X.expr0);
2796ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      dst = newVRegV(env);
2797ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env, mk_vMOVsd_RR(rX,dst));
2798ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env, AMD64Instr_Test64(0xFF, r8));
2799ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env, AMD64Instr_SseCMov(Acc_Z,r0,dst));
2800ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return dst;
2801ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2802ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2803ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ppIRExpr(e);
2804ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vpanic("iselDblExpr_wrk");
2805ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2806ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2807ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2808ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------*/
2809ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- ISEL: SIMD (Vector) expressions, 128 bit.         ---*/
2810ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------*/
2811ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2812ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic HReg iselVecExpr ( ISelEnv* env, IRExpr* e )
2813ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2814ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   HReg r = iselVecExpr_wrk( env, e );
2815ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  if 0
2816ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vex_printf("\n"); ppIRExpr(e); vex_printf("\n");
2817ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  endif
2818ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(hregClass(r) == HRcVec128);
2819ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(hregIsVirtual(r));
2820ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return r;
2821ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2822ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2823ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2824ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* DO NOT CALL THIS DIRECTLY */
2825ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic HReg iselVecExpr_wrk ( ISelEnv* env, IRExpr* e )
2826ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2827ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   HWord      fn = 0; /* address of helper fn, if required */
2828ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Bool       arg1isEReg = False;
2829ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   AMD64SseOp op = Asse_INVALID;
2830ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRType     ty = typeOfIRExpr(env->type_env,e);
2831ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(e);
2832ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(ty == Ity_V128);
2833ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2834ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_RdTmp) {
2835ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return lookupIRTemp(env, e->Iex.RdTmp.tmp);
2836ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2837ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2838ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_Get) {
2839ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HReg dst = newVRegV(env);
2840ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env, AMD64Instr_SseLdSt(
2841ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       True/*load*/,
2842ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       16,
2843ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       dst,
2844ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       AMD64AMode_IR(e->Iex.Get.offset, hregAMD64_RBP())
2845ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    )
2846ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              );
2847ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return dst;
2848ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2849ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2850ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_Load && e->Iex.Load.end == Iend_LE) {
2851ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HReg        dst = newVRegV(env);
2852ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      AMD64AMode* am  = iselIntExpr_AMode(env, e->Iex.Load.addr);
2853ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env, AMD64Instr_SseLdSt( True/*load*/, 16, dst, am ));
2854ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return dst;
2855ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2856ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2857ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_Const) {
2858ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HReg dst = newVRegV(env);
2859ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert(e->Iex.Const.con->tag == Ico_V128);
2860ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch (e->Iex.Const.con->Ico.V128) {
2861ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case 0x0000:
2862ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            dst = generate_zeroes_V128(env);
2863ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
2864ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case 0xFFFF:
2865ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            dst = generate_ones_V128(env);
2866ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
2867ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         default: {
2868ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            AMD64AMode* rsp0 = AMD64AMode_IR(0, hregAMD64_RSP());
2869ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* do push_uimm64 twice, first time for the high-order half. */
2870ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            push_uimm64(env, bitmask8_to_bytemask64(
2871ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                (e->Iex.Const.con->Ico.V128 >> 8) & 0xFF
2872ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       ));
2873ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            push_uimm64(env, bitmask8_to_bytemask64(
2874ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                (e->Iex.Const.con->Ico.V128 >> 0) & 0xFF
2875ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       ));
2876ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, AMD64Instr_SseLdSt( True/*load*/, 16, dst, rsp0 ));
2877ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            add_to_rsp(env, 16);
2878ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
2879ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
2880ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2881ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return dst;
2882ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2883ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2884ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_Unop) {
2885ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (e->Iex.Unop.op) {
2886ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2887ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_NotV128: {
2888ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg arg = iselVecExpr(env, e->Iex.Unop.arg);
2889ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return do_sse_NotV128(env, arg);
2890ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2891ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2892ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpNEZ64x2: {
2893ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* We can use SSE2 instructions for this. */
2894ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Ideally, we want to do a 64Ix2 comparison against zero of
2895ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            the operand.  Problem is no such insn exists.  Solution
2896ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            therefore is to do a 32Ix4 comparison instead, and bitwise-
2897ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            negate (NOT) the result.  Let a,b,c,d be 32-bit lanes, and
2898ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            let the not'd result of this initial comparison be a:b:c:d.
2899ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            What we need to compute is (a|b):(a|b):(c|d):(c|d).  So, use
2900ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            pshufd to create a value b:a:d:c, and OR that with a:b:c:d,
2901ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            giving the required result.
2902ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2903ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            The required selection sequence is 2,3,0,1, which
2904ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            according to Intel's documentation means the pshufd
2905ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            literal value is 0xB1, that is,
2906ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            (2 << 6) | (3 << 4) | (0 << 2) | (1 << 0)
2907ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         */
2908ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg arg  = iselVecExpr(env, e->Iex.Unop.arg);
2909ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg tmp  = generate_zeroes_V128(env);
2910ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg dst  = newVRegV(env);
2911ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, AMD64Instr_SseReRg(Asse_CMPEQ32, arg, tmp));
2912ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         tmp = do_sse_NotV128(env, tmp);
2913ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, AMD64Instr_SseShuf(0xB1, tmp, dst));
2914ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, AMD64Instr_SseReRg(Asse_OR, tmp, dst));
2915ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return dst;
2916ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2917ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2918ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpNEZ32x4: op = Asse_CMPEQ32; goto do_CmpNEZ_vector;
2919ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpNEZ16x8: op = Asse_CMPEQ16; goto do_CmpNEZ_vector;
2920ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpNEZ8x16: op = Asse_CMPEQ8;  goto do_CmpNEZ_vector;
2921ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      do_CmpNEZ_vector:
2922ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      {
2923ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg arg  = iselVecExpr(env, e->Iex.Unop.arg);
2924ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg tmp  = newVRegV(env);
2925ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg zero = generate_zeroes_V128(env);
2926ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg dst;
2927ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, mk_vMOVsd_RR(arg, tmp));
2928ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, AMD64Instr_SseReRg(op, zero, tmp));
2929ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         dst = do_sse_NotV128(env, tmp);
2930ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return dst;
2931ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2932ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2933ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Recip32Fx4: op = Asse_RCPF;   goto do_32Fx4_unary;
2934ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_RSqrt32Fx4: op = Asse_RSQRTF; goto do_32Fx4_unary;
2935ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Sqrt32Fx4:  op = Asse_SQRTF;  goto do_32Fx4_unary;
2936ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      do_32Fx4_unary:
2937ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      {
2938ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg arg = iselVecExpr(env, e->Iex.Unop.arg);
2939ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg dst = newVRegV(env);
2940ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, AMD64Instr_Sse32Fx4(op, arg, dst));
2941ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return dst;
2942ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2943ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2944ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Sqrt64Fx2:  op = Asse_SQRTF;  goto do_64Fx2_unary;
2945ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      do_64Fx2_unary:
2946ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      {
2947ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg arg = iselVecExpr(env, e->Iex.Unop.arg);
2948ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg dst = newVRegV(env);
2949ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, AMD64Instr_Sse64Fx2(op, arg, dst));
2950ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return dst;
2951ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2952ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2953ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Recip32F0x4: op = Asse_RCPF;   goto do_32F0x4_unary;
2954ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_RSqrt32F0x4: op = Asse_RSQRTF; goto do_32F0x4_unary;
2955ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Sqrt32F0x4:  op = Asse_SQRTF;  goto do_32F0x4_unary;
2956ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      do_32F0x4_unary:
2957ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      {
2958ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* A bit subtle.  We have to copy the arg to the result
2959ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            register first, because actually doing the SSE scalar insn
2960ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            leaves the upper 3/4 of the destination register
2961ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            unchanged.  Whereas the required semantics of these
2962ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            primops is that the upper 3/4 is simply copied in from the
2963ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            argument. */
2964ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg arg = iselVecExpr(env, e->Iex.Unop.arg);
2965ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg dst = newVRegV(env);
2966ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, mk_vMOVsd_RR(arg, dst));
2967ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, AMD64Instr_Sse32FLo(op, arg, dst));
2968ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return dst;
2969ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2970ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2971ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Sqrt64F0x2:  op = Asse_SQRTF;  goto do_64F0x2_unary;
2972ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      do_64F0x2_unary:
2973ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      {
2974ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* A bit subtle.  We have to copy the arg to the result
2975ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            register first, because actually doing the SSE scalar insn
2976ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            leaves the upper half of the destination register
2977ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            unchanged.  Whereas the required semantics of these
2978ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            primops is that the upper half is simply copied in from the
2979ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            argument. */
2980ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg arg = iselVecExpr(env, e->Iex.Unop.arg);
2981ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg dst = newVRegV(env);
2982ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, mk_vMOVsd_RR(arg, dst));
2983ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, AMD64Instr_Sse64FLo(op, arg, dst));
2984ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return dst;
2985ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2986ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2987ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_32UtoV128: {
2988ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg        dst     = newVRegV(env);
2989ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         AMD64AMode* rsp_m32 = AMD64AMode_IR(-32, hregAMD64_RSP());
2990ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         AMD64RI*    ri      = iselIntExpr_RI(env, e->Iex.Unop.arg);
2991ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, AMD64Instr_Alu64M(Aalu_MOV, ri, rsp_m32));
2992ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, AMD64Instr_SseLdzLO(4, dst, rsp_m32));
2993ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return dst;
2994ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2995ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2996ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_64UtoV128: {
2997ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg        dst  = newVRegV(env);
2998ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         AMD64AMode* rsp0 = AMD64AMode_IR(0, hregAMD64_RSP());
2999ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         AMD64RMI*   rmi  = iselIntExpr_RMI(env, e->Iex.Unop.arg);
3000ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, AMD64Instr_Push(rmi));
3001ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, AMD64Instr_SseLdzLO(8, dst, rsp0));
3002ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         add_to_rsp(env, 8);
3003ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return dst;
3004ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3005ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3006663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Iop_V256toV128_0:
3007663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Iop_V256toV128_1: {
3008663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         HReg vHi, vLo;
3009663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         iselDVecExpr(&vHi, &vLo, env, e->Iex.Unop.arg);
3010663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         return (e->Iex.Unop.op == Iop_V256toV128_1) ? vHi : vLo;
3011663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
3012663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3013ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
3014ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
3015ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } /* switch (e->Iex.Unop.op) */
3016ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } /* if (e->tag == Iex_Unop) */
3017ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3018ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_Binop) {
3019ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (e->Iex.Binop.op) {
3020ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3021663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* FIXME: could we generate MOVQ here? */
3022ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_SetV128lo64: {
3023ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg dst  = newVRegV(env);
3024ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg srcV = iselVecExpr(env, e->Iex.Binop.arg1);
3025ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg srcI = iselIntExpr_R(env, e->Iex.Binop.arg2);
3026ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         AMD64AMode* rsp_m16 = AMD64AMode_IR(-16, hregAMD64_RSP());
3027ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, AMD64Instr_SseLdSt(False/*store*/, 16, srcV, rsp_m16));
3028ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, AMD64Instr_Alu64M(Aalu_MOV, AMD64RI_Reg(srcI), rsp_m16));
3029ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, AMD64Instr_SseLdSt(True/*load*/, 16, dst, rsp_m16));
3030ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return dst;
3031ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3032ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3033663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* FIXME: could we generate MOVD here? */
3034ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_SetV128lo32: {
3035ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg dst  = newVRegV(env);
3036ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg srcV = iselVecExpr(env, e->Iex.Binop.arg1);
3037ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg srcI = iselIntExpr_R(env, e->Iex.Binop.arg2);
3038ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         AMD64AMode* rsp_m16 = AMD64AMode_IR(-16, hregAMD64_RSP());
3039ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, AMD64Instr_SseLdSt(False/*store*/, 16, srcV, rsp_m16));
3040ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, AMD64Instr_Store(4, srcI, rsp_m16));
3041ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, AMD64Instr_SseLdSt(True/*load*/, 16, dst, rsp_m16));
3042ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return dst;
3043ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3044ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3045ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_64HLtoV128: {
3046663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         HReg        rsp     = hregAMD64_RSP();
3047663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         AMD64AMode* m8_rsp  = AMD64AMode_IR(-8, rsp);
3048663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         AMD64AMode* m16_rsp = AMD64AMode_IR(-16, rsp);
3049663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         AMD64RI*    qHi = iselIntExpr_RI(env, e->Iex.Binop.arg1);
3050663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         AMD64RI*    qLo = iselIntExpr_RI(env, e->Iex.Binop.arg2);
3051663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         addInstr(env, AMD64Instr_Alu64M(Aalu_MOV, qHi, m8_rsp));
3052663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         addInstr(env, AMD64Instr_Alu64M(Aalu_MOV, qLo, m16_rsp));
3053ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg        dst = newVRegV(env);
3054663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* One store-forwarding stall coming up, oh well :-( */
3055663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         addInstr(env, AMD64Instr_SseLdSt(True/*load*/, 16, dst, m16_rsp));
3056ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return dst;
3057ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3058ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3059ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpEQ32Fx4: op = Asse_CMPEQF; goto do_32Fx4;
3060ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpLT32Fx4: op = Asse_CMPLTF; goto do_32Fx4;
3061ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpLE32Fx4: op = Asse_CMPLEF; goto do_32Fx4;
3062ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpUN32Fx4: op = Asse_CMPUNF; goto do_32Fx4;
3063ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Add32Fx4:   op = Asse_ADDF;   goto do_32Fx4;
3064ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Div32Fx4:   op = Asse_DIVF;   goto do_32Fx4;
3065ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Max32Fx4:   op = Asse_MAXF;   goto do_32Fx4;
3066ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Min32Fx4:   op = Asse_MINF;   goto do_32Fx4;
3067ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Mul32Fx4:   op = Asse_MULF;   goto do_32Fx4;
3068ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Sub32Fx4:   op = Asse_SUBF;   goto do_32Fx4;
3069ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      do_32Fx4:
3070ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      {
3071ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg argL = iselVecExpr(env, e->Iex.Binop.arg1);
3072ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg argR = iselVecExpr(env, e->Iex.Binop.arg2);
3073ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg dst = newVRegV(env);
3074ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, mk_vMOVsd_RR(argL, dst));
3075ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, AMD64Instr_Sse32Fx4(op, argR, dst));
3076ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return dst;
3077ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3078ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3079ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpEQ64Fx2: op = Asse_CMPEQF; goto do_64Fx2;
3080ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpLT64Fx2: op = Asse_CMPLTF; goto do_64Fx2;
3081ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpLE64Fx2: op = Asse_CMPLEF; goto do_64Fx2;
3082ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpUN64Fx2: op = Asse_CMPUNF; goto do_64Fx2;
3083ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Add64Fx2:   op = Asse_ADDF;   goto do_64Fx2;
3084ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Div64Fx2:   op = Asse_DIVF;   goto do_64Fx2;
3085ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Max64Fx2:   op = Asse_MAXF;   goto do_64Fx2;
3086ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Min64Fx2:   op = Asse_MINF;   goto do_64Fx2;
3087ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Mul64Fx2:   op = Asse_MULF;   goto do_64Fx2;
3088ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Sub64Fx2:   op = Asse_SUBF;   goto do_64Fx2;
3089ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      do_64Fx2:
3090ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      {
3091ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg argL = iselVecExpr(env, e->Iex.Binop.arg1);
3092ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg argR = iselVecExpr(env, e->Iex.Binop.arg2);
3093ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg dst = newVRegV(env);
3094ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, mk_vMOVsd_RR(argL, dst));
3095ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, AMD64Instr_Sse64Fx2(op, argR, dst));
3096ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return dst;
3097ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3098ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3099ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpEQ32F0x4: op = Asse_CMPEQF; goto do_32F0x4;
3100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpLT32F0x4: op = Asse_CMPLTF; goto do_32F0x4;
3101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpLE32F0x4: op = Asse_CMPLEF; goto do_32F0x4;
3102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpUN32F0x4: op = Asse_CMPUNF; goto do_32F0x4;
3103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Add32F0x4:   op = Asse_ADDF;   goto do_32F0x4;
3104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Div32F0x4:   op = Asse_DIVF;   goto do_32F0x4;
3105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Max32F0x4:   op = Asse_MAXF;   goto do_32F0x4;
3106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Min32F0x4:   op = Asse_MINF;   goto do_32F0x4;
3107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Mul32F0x4:   op = Asse_MULF;   goto do_32F0x4;
3108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Sub32F0x4:   op = Asse_SUBF;   goto do_32F0x4;
3109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      do_32F0x4: {
3110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg argL = iselVecExpr(env, e->Iex.Binop.arg1);
3111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg argR = iselVecExpr(env, e->Iex.Binop.arg2);
3112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg dst = newVRegV(env);
3113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, mk_vMOVsd_RR(argL, dst));
3114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, AMD64Instr_Sse32FLo(op, argR, dst));
3115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return dst;
3116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpEQ64F0x2: op = Asse_CMPEQF; goto do_64F0x2;
3119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpLT64F0x2: op = Asse_CMPLTF; goto do_64F0x2;
3120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpLE64F0x2: op = Asse_CMPLEF; goto do_64F0x2;
3121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpUN64F0x2: op = Asse_CMPUNF; goto do_64F0x2;
3122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Add64F0x2:   op = Asse_ADDF;   goto do_64F0x2;
3123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Div64F0x2:   op = Asse_DIVF;   goto do_64F0x2;
3124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Max64F0x2:   op = Asse_MAXF;   goto do_64F0x2;
3125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Min64F0x2:   op = Asse_MINF;   goto do_64F0x2;
3126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Mul64F0x2:   op = Asse_MULF;   goto do_64F0x2;
3127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Sub64F0x2:   op = Asse_SUBF;   goto do_64F0x2;
3128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      do_64F0x2: {
3129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg argL = iselVecExpr(env, e->Iex.Binop.arg1);
3130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg argR = iselVecExpr(env, e->Iex.Binop.arg2);
3131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg dst = newVRegV(env);
3132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, mk_vMOVsd_RR(argL, dst));
3133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, AMD64Instr_Sse64FLo(op, argR, dst));
3134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return dst;
3135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3137b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_QNarrowBin32Sto16Sx8:
3138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         op = Asse_PACKSSD; arg1isEReg = True; goto do_SseReRg;
3139b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_QNarrowBin16Sto8Sx16:
3140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         op = Asse_PACKSSW; arg1isEReg = True; goto do_SseReRg;
3141b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_QNarrowBin16Sto8Ux16:
3142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         op = Asse_PACKUSW; arg1isEReg = True; goto do_SseReRg;
3143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_InterleaveHI8x16:
3145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         op = Asse_UNPCKHB; arg1isEReg = True; goto do_SseReRg;
3146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_InterleaveHI16x8:
3147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         op = Asse_UNPCKHW; arg1isEReg = True; goto do_SseReRg;
3148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_InterleaveHI32x4:
3149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         op = Asse_UNPCKHD; arg1isEReg = True; goto do_SseReRg;
3150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_InterleaveHI64x2:
3151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         op = Asse_UNPCKHQ; arg1isEReg = True; goto do_SseReRg;
3152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_InterleaveLO8x16:
3154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         op = Asse_UNPCKLB; arg1isEReg = True; goto do_SseReRg;
3155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_InterleaveLO16x8:
3156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         op = Asse_UNPCKLW; arg1isEReg = True; goto do_SseReRg;
3157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_InterleaveLO32x4:
3158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         op = Asse_UNPCKLD; arg1isEReg = True; goto do_SseReRg;
3159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_InterleaveLO64x2:
3160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         op = Asse_UNPCKLQ; arg1isEReg = True; goto do_SseReRg;
3161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_AndV128:    op = Asse_AND;      goto do_SseReRg;
3163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_OrV128:     op = Asse_OR;       goto do_SseReRg;
3164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_XorV128:    op = Asse_XOR;      goto do_SseReRg;
3165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Add8x16:    op = Asse_ADD8;     goto do_SseReRg;
3166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Add16x8:    op = Asse_ADD16;    goto do_SseReRg;
3167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Add32x4:    op = Asse_ADD32;    goto do_SseReRg;
3168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Add64x2:    op = Asse_ADD64;    goto do_SseReRg;
3169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QAdd8Sx16:  op = Asse_QADD8S;   goto do_SseReRg;
3170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QAdd16Sx8:  op = Asse_QADD16S;  goto do_SseReRg;
3171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QAdd8Ux16:  op = Asse_QADD8U;   goto do_SseReRg;
3172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QAdd16Ux8:  op = Asse_QADD16U;  goto do_SseReRg;
3173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Avg8Ux16:   op = Asse_AVG8U;    goto do_SseReRg;
3174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Avg16Ux8:   op = Asse_AVG16U;   goto do_SseReRg;
3175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpEQ8x16:  op = Asse_CMPEQ8;   goto do_SseReRg;
3176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpEQ16x8:  op = Asse_CMPEQ16;  goto do_SseReRg;
3177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpEQ32x4:  op = Asse_CMPEQ32;  goto do_SseReRg;
3178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpGT8Sx16: op = Asse_CMPGT8S;  goto do_SseReRg;
3179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpGT16Sx8: op = Asse_CMPGT16S; goto do_SseReRg;
3180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpGT32Sx4: op = Asse_CMPGT32S; goto do_SseReRg;
3181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Max16Sx8:   op = Asse_MAX16S;   goto do_SseReRg;
3182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Max8Ux16:   op = Asse_MAX8U;    goto do_SseReRg;
3183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Min16Sx8:   op = Asse_MIN16S;   goto do_SseReRg;
3184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Min8Ux16:   op = Asse_MIN8U;    goto do_SseReRg;
3185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_MulHi16Ux8: op = Asse_MULHI16U; goto do_SseReRg;
3186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_MulHi16Sx8: op = Asse_MULHI16S; goto do_SseReRg;
3187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Mul16x8:    op = Asse_MUL16;    goto do_SseReRg;
3188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Sub8x16:    op = Asse_SUB8;     goto do_SseReRg;
3189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Sub16x8:    op = Asse_SUB16;    goto do_SseReRg;
3190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Sub32x4:    op = Asse_SUB32;    goto do_SseReRg;
3191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Sub64x2:    op = Asse_SUB64;    goto do_SseReRg;
3192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QSub8Sx16:  op = Asse_QSUB8S;   goto do_SseReRg;
3193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QSub16Sx8:  op = Asse_QSUB16S;  goto do_SseReRg;
3194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QSub8Ux16:  op = Asse_QSUB8U;   goto do_SseReRg;
3195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_QSub16Ux8:  op = Asse_QSUB16U;  goto do_SseReRg;
3196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      do_SseReRg: {
3197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg arg1 = iselVecExpr(env, e->Iex.Binop.arg1);
3198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg arg2 = iselVecExpr(env, e->Iex.Binop.arg2);
3199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg dst = newVRegV(env);
3200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (arg1isEReg) {
3201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, mk_vMOVsd_RR(arg2, dst));
3202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, AMD64Instr_SseReRg(op, arg1, dst));
3203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
3204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, mk_vMOVsd_RR(arg1, dst));
3205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, AMD64Instr_SseReRg(op, arg2, dst));
3206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
3207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return dst;
3208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_ShlN16x8: op = Asse_SHL16; goto do_SseShift;
3211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_ShlN32x4: op = Asse_SHL32; goto do_SseShift;
3212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_ShlN64x2: op = Asse_SHL64; goto do_SseShift;
3213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_SarN16x8: op = Asse_SAR16; goto do_SseShift;
3214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_SarN32x4: op = Asse_SAR32; goto do_SseShift;
3215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_ShrN16x8: op = Asse_SHR16; goto do_SseShift;
3216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_ShrN32x4: op = Asse_SHR32; goto do_SseShift;
3217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_ShrN64x2: op = Asse_SHR64; goto do_SseShift;
3218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      do_SseShift: {
3219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg        greg = iselVecExpr(env, e->Iex.Binop.arg1);
3220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         AMD64RMI*   rmi  = iselIntExpr_RMI(env, e->Iex.Binop.arg2);
3221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         AMD64AMode* rsp0 = AMD64AMode_IR(0, hregAMD64_RSP());
3222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg        ereg = newVRegV(env);
3223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg        dst  = newVRegV(env);
3224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, AMD64Instr_Push(AMD64RMI_Imm(0)));
3225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, AMD64Instr_Push(rmi));
3226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, AMD64Instr_SseLdSt(True/*load*/, 16, ereg, rsp0));
3227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, mk_vMOVsd_RR(greg, dst));
3228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, AMD64Instr_SseReRg(op, ereg, dst));
3229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         add_to_rsp(env, 16);
3230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return dst;
3231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Mul32x4:    fn = (HWord)h_generic_calc_Mul32x4;
3234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           goto do_SseAssistedBinary;
3235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Max32Sx4:   fn = (HWord)h_generic_calc_Max32Sx4;
3236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           goto do_SseAssistedBinary;
3237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Min32Sx4:   fn = (HWord)h_generic_calc_Min32Sx4;
3238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           goto do_SseAssistedBinary;
3239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Max32Ux4:   fn = (HWord)h_generic_calc_Max32Ux4;
3240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           goto do_SseAssistedBinary;
3241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Min32Ux4:   fn = (HWord)h_generic_calc_Min32Ux4;
3242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           goto do_SseAssistedBinary;
3243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Max16Ux8:   fn = (HWord)h_generic_calc_Max16Ux8;
3244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           goto do_SseAssistedBinary;
3245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Min16Ux8:   fn = (HWord)h_generic_calc_Min16Ux8;
3246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           goto do_SseAssistedBinary;
3247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Max8Sx16:   fn = (HWord)h_generic_calc_Max8Sx16;
3248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           goto do_SseAssistedBinary;
3249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_Min8Sx16:   fn = (HWord)h_generic_calc_Min8Sx16;
3250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           goto do_SseAssistedBinary;
3251b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_CmpEQ64x2:  fn = (HWord)h_generic_calc_CmpEQ64x2;
3252b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                           goto do_SseAssistedBinary;
3253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Iop_CmpGT64Sx2: fn = (HWord)h_generic_calc_CmpGT64Sx2;
3254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           goto do_SseAssistedBinary;
3255663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Iop_Perm32x4:   fn = (HWord)h_generic_calc_Perm32x4;
3256663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                           goto do_SseAssistedBinary;
3257b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_QNarrowBin32Sto16Ux8:
3258b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                           fn = (HWord)h_generic_calc_QNarrowBin32Sto16Ux8;
3259b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                           goto do_SseAssistedBinary;
3260b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_NarrowBin16to8x16:
3261b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                           fn = (HWord)h_generic_calc_NarrowBin16to8x16;
3262b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                           goto do_SseAssistedBinary;
3263b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case Iop_NarrowBin32to16x8:
3264b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                           fn = (HWord)h_generic_calc_NarrowBin32to16x8;
3265b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                           goto do_SseAssistedBinary;
3266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      do_SseAssistedBinary: {
3267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* RRRufff!  RRRufff code is what we're generating here.  Oh
3268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            well. */
3269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(fn != 0);
3270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg dst = newVRegV(env);
3271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg argL = iselVecExpr(env, e->Iex.Binop.arg1);
3272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg argR = iselVecExpr(env, e->Iex.Binop.arg2);
3273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg argp = newVRegI(env);
3274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* subq $112, %rsp         -- make a space*/
3275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         sub_from_rsp(env, 112);
3276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* leaq 48(%rsp), %r_argp  -- point into it */
3277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, AMD64Instr_Lea64(AMD64AMode_IR(48, hregAMD64_RSP()),
3278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                        argp));
3279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* andq $-16, %r_argp      -- 16-align the pointer */
3280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, AMD64Instr_Alu64R(Aalu_AND,
3281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                         AMD64RMI_Imm( ~(UInt)15 ),
3282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                         argp));
3283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Prepare 3 arg regs:
3284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            leaq 0(%r_argp), %rdi
3285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            leaq 16(%r_argp), %rsi
3286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            leaq 32(%r_argp), %rdx
3287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         */
3288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, AMD64Instr_Lea64(AMD64AMode_IR(0, argp),
3289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                        hregAMD64_RDI()));
3290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, AMD64Instr_Lea64(AMD64AMode_IR(16, argp),
3291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                        hregAMD64_RSI()));
3292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, AMD64Instr_Lea64(AMD64AMode_IR(32, argp),
3293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                        hregAMD64_RDX()));
3294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Store the two args, at (%rsi) and (%rdx):
3295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            movupd  %argL, 0(%rsi)
3296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            movupd  %argR, 0(%rdx)
3297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         */
3298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, AMD64Instr_SseLdSt(False/*!isLoad*/, 16, argL,
3299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                          AMD64AMode_IR(0, hregAMD64_RSI())));
3300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, AMD64Instr_SseLdSt(False/*!isLoad*/, 16, argR,
3301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                          AMD64AMode_IR(0, hregAMD64_RDX())));
3302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* call the helper */
3303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, AMD64Instr_Call( Acc_ALWAYS, (ULong)fn, 3 ));
3304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* fetch the result from memory, using %r_argp, which the
3305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            register allocator will keep alive across the call. */
3306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, AMD64Instr_SseLdSt(True/*isLoad*/, 16, dst,
3307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                          AMD64AMode_IR(0, argp)));
3308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* and finally, clear the space */
3309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         add_to_rsp(env, 112);
3310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return dst;
3311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3313f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root      case Iop_SarN64x2: fn = (HWord)h_generic_calc_SarN64x2;
3314f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root                         goto do_SseAssistedVectorAndScalar;
3315f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root      case Iop_SarN8x16: fn = (HWord)h_generic_calc_SarN8x16;
3316f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root                         goto do_SseAssistedVectorAndScalar;
3317f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root      do_SseAssistedVectorAndScalar: {
3318f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root         /* RRRufff!  RRRufff code is what we're generating here.  Oh
3319f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root            well. */
3320f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root         vassert(fn != 0);
3321f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root         HReg dst = newVRegV(env);
3322f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root         HReg argL = iselVecExpr(env, e->Iex.Binop.arg1);
3323f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root         HReg argR = iselIntExpr_R(env, e->Iex.Binop.arg2);
3324f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root         HReg argp = newVRegI(env);
3325f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root         /* subq $112, %rsp         -- make a space*/
3326f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root         sub_from_rsp(env, 112);
3327f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root         /* leaq 48(%rsp), %r_argp  -- point into it */
3328f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root         addInstr(env, AMD64Instr_Lea64(AMD64AMode_IR(48, hregAMD64_RSP()),
3329f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root                                        argp));
3330f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root         /* andq $-16, %r_argp      -- 16-align the pointer */
3331f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root         addInstr(env, AMD64Instr_Alu64R(Aalu_AND,
3332f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root                                         AMD64RMI_Imm( ~(UInt)15 ),
3333f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root                                         argp));
3334f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root         /* Prepare 2 vector arg regs:
3335f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root            leaq 0(%r_argp), %rdi
3336f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root            leaq 16(%r_argp), %rsi
3337f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root         */
3338f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root         addInstr(env, AMD64Instr_Lea64(AMD64AMode_IR(0, argp),
3339f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root                                        hregAMD64_RDI()));
3340f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root         addInstr(env, AMD64Instr_Lea64(AMD64AMode_IR(16, argp),
3341f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root                                        hregAMD64_RSI()));
3342f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root         /* Store the vector arg, at (%rsi):
3343f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root            movupd  %argL, 0(%rsi)
3344f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root         */
3345f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root         addInstr(env, AMD64Instr_SseLdSt(False/*!isLoad*/, 16, argL,
3346f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root                                          AMD64AMode_IR(0, hregAMD64_RSI())));
3347f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root         /* And get the scalar value into rdx */
3348f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root         addInstr(env, mk_iMOVsd_RR(argR, hregAMD64_RDX()));
3349f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root
3350f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root         /* call the helper */
3351f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root         addInstr(env, AMD64Instr_Call( Acc_ALWAYS, (ULong)fn, 3 ));
3352f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root         /* fetch the result from memory, using %r_argp, which the
3353f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root            register allocator will keep alive across the call. */
3354f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root         addInstr(env, AMD64Instr_SseLdSt(True/*isLoad*/, 16, dst,
3355f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root                                          AMD64AMode_IR(0, argp)));
3356f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root         /* and finally, clear the space */
3357f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root         add_to_rsp(env, 112);
3358f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root         return dst;
3359f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root      }
3360f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root
3361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
3362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
3363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } /* switch (e->Iex.Binop.op) */
3364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } /* if (e->tag == Iex_Binop) */
3365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (e->tag == Iex_Mux0X) {
3367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HReg r8  = iselIntExpr_R(env, e->Iex.Mux0X.cond);
3368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HReg rX  = iselVecExpr(env, e->Iex.Mux0X.exprX);
3369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HReg r0  = iselVecExpr(env, e->Iex.Mux0X.expr0);
3370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HReg dst = newVRegV(env);
3371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env, mk_vMOVsd_RR(rX,dst));
3372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env, AMD64Instr_Test64(0xFF, r8));
3373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addInstr(env, AMD64Instr_SseCMov(Acc_Z,r0,dst));
3374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return dst;
3375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //vec_fail:
3378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vex_printf("iselVecExpr (amd64, subarch = %s): can't reduce\n",
3379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              LibVEX_ppVexHwCaps(VexArchAMD64, env->hwcaps));
3380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ppIRExpr(e);
3381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vpanic("iselVecExpr_wrk");
3382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------*/
3386663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/*--- ISEL: SIMD (V256) expressions, into 2 XMM regs.    --*/
3387663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/*---------------------------------------------------------*/
3388663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3389663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic void iselDVecExpr ( /*OUT*/HReg* rHi, /*OUT*/HReg* rLo,
3390663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                           ISelEnv* env, IRExpr* e )
3391663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
3392663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   iselDVecExpr_wrk( rHi, rLo, env, e );
3393663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#  if 0
3394663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vex_printf("\n"); ppIRExpr(e); vex_printf("\n");
3395663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#  endif
3396663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vassert(hregClass(*rHi) == HRcVec128);
3397663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vassert(hregClass(*rLo) == HRcVec128);
3398663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vassert(hregIsVirtual(*rHi));
3399663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vassert(hregIsVirtual(*rLo));
3400663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
3401663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3402663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3403663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* DO NOT CALL THIS DIRECTLY */
3404663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic void iselDVecExpr_wrk ( /*OUT*/HReg* rHi, /*OUT*/HReg* rLo,
3405663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                               ISelEnv* env, IRExpr* e )
3406663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
3407663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vassert(e);
3408663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRType ty = typeOfIRExpr(env->type_env,e);
3409663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vassert(ty == Ity_V256);
3410663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3411663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   AMD64SseOp op = Asse_INVALID;
3412663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3413663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* read 256-bit IRTemp */
3414663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (e->tag == Iex_RdTmp) {
3415663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      lookupIRTempPair( rHi, rLo, env, e->Iex.RdTmp.tmp);
3416663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      return;
3417663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
3418663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3419663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (e->tag == Iex_Get) {
3420663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      HReg        vHi  = newVRegV(env);
3421663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      HReg        vLo  = newVRegV(env);
3422663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      HReg        rbp  = hregAMD64_RBP();
3423663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      AMD64AMode* am0  = AMD64AMode_IR(e->Iex.Get.offset + 0,  rbp);
3424663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      AMD64AMode* am16 = AMD64AMode_IR(e->Iex.Get.offset + 16, rbp);
3425663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      addInstr(env, AMD64Instr_SseLdSt(True/*load*/, 16, vLo, am0));
3426663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      addInstr(env, AMD64Instr_SseLdSt(True/*load*/, 16, vHi, am16));
3427663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      *rHi = vHi;
3428663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      *rLo = vLo;
3429663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      return;
3430663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
3431663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3432663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (e->tag == Iex_Load) {
3433663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      HReg        vHi  = newVRegV(env);
3434663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      HReg        vLo  = newVRegV(env);
3435663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      HReg        rA   = iselIntExpr_R(env, e->Iex.Load.addr);
3436663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      AMD64AMode* am0  = AMD64AMode_IR(0,  rA);
3437663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      AMD64AMode* am16 = AMD64AMode_IR(16, rA);
3438663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      addInstr(env, AMD64Instr_SseLdSt(True/*load*/, 16, vLo, am0));
3439663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      addInstr(env, AMD64Instr_SseLdSt(True/*load*/, 16, vHi, am16));
3440663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      *rHi = vHi;
3441663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      *rLo = vLo;
3442663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      return;
3443663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
3444663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3445663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (e->tag == Iex_Const) {
3446663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      vassert(e->Iex.Const.con->tag == Ico_V256);
3447663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      switch (e->Iex.Const.con->Ico.V256) {
3448663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case 0x00000000: {
3449663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            HReg vHi = generate_zeroes_V128(env);
3450663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            HReg vLo = newVRegV(env);
3451663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addInstr(env, mk_vMOVsd_RR(vHi, vLo));
3452663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            *rHi = vHi;
3453663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            *rLo = vLo;
3454663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            return;
3455663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
3456663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         default:
3457663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            break; /* give up.   Until such time as is necessary. */
3458663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
3459663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
3460663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3461663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (e->tag == Iex_Unop) {
3462663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   switch (e->Iex.Unop.op) {
3463663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3464663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Iop_NotV256: {
3465663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         HReg argHi, argLo;
3466663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         iselDVecExpr(&argHi, &argLo, env, e->Iex.Unop.arg);
3467663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         *rHi = do_sse_NotV128(env, argHi);
3468663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         *rLo = do_sse_NotV128(env, argLo);
3469663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         return;
3470663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
3471663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3472663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Iop_Recip32Fx8: op = Asse_RCPF;   goto do_32Fx8_unary;
3473663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Iop_Sqrt32Fx8:  op = Asse_SQRTF;  goto do_32Fx8_unary;
3474663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Iop_RSqrt32Fx8: op = Asse_RSQRTF; goto do_32Fx8_unary;
3475663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      do_32Fx8_unary:
3476663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      {
3477663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         HReg argHi, argLo;
3478663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         iselDVecExpr(&argHi, &argLo, env, e->Iex.Unop.arg);
3479663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         HReg dstHi = newVRegV(env);
3480663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         HReg dstLo = newVRegV(env);
3481663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         addInstr(env, AMD64Instr_Sse32Fx4(op, argHi, dstHi));
3482663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         addInstr(env, AMD64Instr_Sse32Fx4(op, argLo, dstLo));
3483663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         *rHi = dstHi;
3484663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         *rLo = dstLo;
3485663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         return;
3486663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
3487663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3488663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Iop_Sqrt64Fx4:  op = Asse_SQRTF;  goto do_64Fx4_unary;
3489663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      do_64Fx4_unary:
3490663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      {
3491663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         HReg argHi, argLo;
3492663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         iselDVecExpr(&argHi, &argLo, env, e->Iex.Unop.arg);
3493663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         HReg dstHi = newVRegV(env);
3494663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         HReg dstLo = newVRegV(env);
3495663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         addInstr(env, AMD64Instr_Sse64Fx2(op, argHi, dstHi));
3496663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         addInstr(env, AMD64Instr_Sse64Fx2(op, argLo, dstLo));
3497663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         *rHi = dstHi;
3498663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         *rLo = dstLo;
3499663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         return;
3500663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
3501663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3502663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Iop_CmpNEZ64x4: {
3503663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* We can use SSE2 instructions for this. */
3504663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* Same scheme as Iop_CmpNEZ64x2, except twice as wide
3505663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            (obviously).  See comment on Iop_CmpNEZ64x2 for
3506663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            explanation of what's going on here. */
3507663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         HReg argHi, argLo;
3508663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         iselDVecExpr(&argHi, &argLo, env, e->Iex.Unop.arg);
3509663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         HReg tmpHi  = generate_zeroes_V128(env);
3510663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         HReg tmpLo  = newVRegV(env);
3511663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         addInstr(env, mk_vMOVsd_RR(tmpHi, tmpLo));
3512663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         HReg dstHi  = newVRegV(env);
3513663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         HReg dstLo  = newVRegV(env);
3514663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         addInstr(env, AMD64Instr_SseReRg(Asse_CMPEQ32, argHi, tmpHi));
3515663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         addInstr(env, AMD64Instr_SseReRg(Asse_CMPEQ32, argLo, tmpLo));
3516663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         tmpHi = do_sse_NotV128(env, tmpHi);
3517663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         tmpLo = do_sse_NotV128(env, tmpLo);
3518663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         addInstr(env, AMD64Instr_SseShuf(0xB1, tmpHi, dstHi));
3519663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         addInstr(env, AMD64Instr_SseShuf(0xB1, tmpLo, dstLo));
3520663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         addInstr(env, AMD64Instr_SseReRg(Asse_OR, tmpHi, dstHi));
3521663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         addInstr(env, AMD64Instr_SseReRg(Asse_OR, tmpLo, dstLo));
3522663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         *rHi = dstHi;
3523663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         *rLo = dstLo;
3524663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         return;
3525663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
3526663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3527663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Iop_CmpNEZ32x8: op = Asse_CMPEQ32; goto do_CmpNEZ_vector;
3528663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      do_CmpNEZ_vector:
3529663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      {
3530663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         HReg argHi, argLo;
3531663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         iselDVecExpr(&argHi, &argLo, env, e->Iex.Unop.arg);
3532663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         HReg tmpHi = newVRegV(env);
3533663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         HReg tmpLo = newVRegV(env);
3534663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         HReg zero  = generate_zeroes_V128(env);
3535663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         HReg dstHi, dstLo;
3536663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         addInstr(env, mk_vMOVsd_RR(argHi, tmpHi));
3537663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         addInstr(env, mk_vMOVsd_RR(argLo, tmpLo));
3538663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         addInstr(env, AMD64Instr_SseReRg(op, zero, tmpHi));
3539663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         addInstr(env, AMD64Instr_SseReRg(op, zero, tmpLo));
3540663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         dstHi = do_sse_NotV128(env, tmpHi);
3541663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         dstLo = do_sse_NotV128(env, tmpLo);
3542663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         *rHi = dstHi;
3543663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         *rLo = dstLo;
3544663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         return;
3545663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
3546663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3547663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      default:
3548663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         break;
3549663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   } /* switch (e->Iex.Unop.op) */
3550663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   } /* if (e->tag == Iex_Unop) */
3551663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3552663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (e->tag == Iex_Binop) {
3553663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   switch (e->Iex.Binop.op) {
3554663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3555663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Iop_Add64Fx4:   op = Asse_ADDF;   goto do_64Fx4;
3556663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Iop_Sub64Fx4:   op = Asse_SUBF;   goto do_64Fx4;
3557663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Iop_Mul64Fx4:   op = Asse_MULF;   goto do_64Fx4;
3558663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Iop_Div64Fx4:   op = Asse_DIVF;   goto do_64Fx4;
3559663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Iop_Max64Fx4:   op = Asse_MAXF;   goto do_64Fx4;
3560663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Iop_Min64Fx4:   op = Asse_MINF;   goto do_64Fx4;
3561663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      do_64Fx4:
3562663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      {
3563663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         HReg argLhi, argLlo, argRhi, argRlo;
3564663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         iselDVecExpr(&argLhi, &argLlo, env, e->Iex.Binop.arg1);
3565663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         iselDVecExpr(&argRhi, &argRlo, env, e->Iex.Binop.arg2);
3566663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         HReg dstHi = newVRegV(env);
3567663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         HReg dstLo = newVRegV(env);
3568663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         addInstr(env, mk_vMOVsd_RR(argLhi, dstHi));
3569663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         addInstr(env, mk_vMOVsd_RR(argLlo, dstLo));
3570663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         addInstr(env, AMD64Instr_Sse64Fx2(op, argRhi, dstHi));
3571663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         addInstr(env, AMD64Instr_Sse64Fx2(op, argRlo, dstLo));
3572663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         *rHi = dstHi;
3573663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         *rLo = dstLo;
3574663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         return;
3575663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
3576663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3577663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Iop_Add32Fx8:   op = Asse_ADDF;   goto do_32Fx8;
3578663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Iop_Sub32Fx8:   op = Asse_SUBF;   goto do_32Fx8;
3579663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Iop_Mul32Fx8:   op = Asse_MULF;   goto do_32Fx8;
3580663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Iop_Div32Fx8:   op = Asse_DIVF;   goto do_32Fx8;
3581663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Iop_Max32Fx8:   op = Asse_MAXF;   goto do_32Fx8;
3582663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Iop_Min32Fx8:   op = Asse_MINF;   goto do_32Fx8;
3583663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      do_32Fx8:
3584663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      {
3585663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         HReg argLhi, argLlo, argRhi, argRlo;
3586663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         iselDVecExpr(&argLhi, &argLlo, env, e->Iex.Binop.arg1);
3587663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         iselDVecExpr(&argRhi, &argRlo, env, e->Iex.Binop.arg2);
3588663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         HReg dstHi = newVRegV(env);
3589663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         HReg dstLo = newVRegV(env);
3590663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         addInstr(env, mk_vMOVsd_RR(argLhi, dstHi));
3591663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         addInstr(env, mk_vMOVsd_RR(argLlo, dstLo));
3592663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         addInstr(env, AMD64Instr_Sse32Fx4(op, argRhi, dstHi));
3593663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         addInstr(env, AMD64Instr_Sse32Fx4(op, argRlo, dstLo));
3594663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         *rHi = dstHi;
3595663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         *rLo = dstLo;
3596663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         return;
3597663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
3598663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3599663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Iop_AndV256:    op = Asse_AND;      goto do_SseReRg;
3600663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Iop_OrV256:     op = Asse_OR;       goto do_SseReRg;
3601663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Iop_XorV256:    op = Asse_XOR;      goto do_SseReRg;
3602663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      do_SseReRg:
3603663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      {
3604663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         HReg argLhi, argLlo, argRhi, argRlo;
3605663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         iselDVecExpr(&argLhi, &argLlo, env, e->Iex.Binop.arg1);
3606663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         iselDVecExpr(&argRhi, &argRlo, env, e->Iex.Binop.arg2);
3607663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         HReg dstHi = newVRegV(env);
3608663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         HReg dstLo = newVRegV(env);
3609663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         addInstr(env, mk_vMOVsd_RR(argLhi, dstHi));
3610663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         addInstr(env, mk_vMOVsd_RR(argLlo, dstLo));
3611663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         addInstr(env, AMD64Instr_SseReRg(op, argRhi, dstHi));
3612663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         addInstr(env, AMD64Instr_SseReRg(op, argRlo, dstLo));
3613663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         *rHi = dstHi;
3614663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         *rLo = dstLo;
3615663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         return;
3616663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
3617663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3618663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Iop_V128HLtoV256: {
3619663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         *rHi = iselVecExpr(env, e->Iex.Binop.arg1);
3620663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         *rLo = iselVecExpr(env, e->Iex.Binop.arg2);
3621663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         return;
3622663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
3623663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3624663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      default:
3625663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         break;
3626663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   } /* switch (e->Iex.Binop.op) */
3627663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   } /* if (e->tag == Iex_Binop) */
3628663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3629663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (e->tag == Iex_Qop && e->Iex.Qop.details->op == Iop_64x4toV256) {
3630663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      HReg        rsp     = hregAMD64_RSP();
3631663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      HReg        vHi     = newVRegV(env);
3632663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      HReg        vLo     = newVRegV(env);
3633663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      AMD64AMode* m8_rsp  = AMD64AMode_IR(-8, rsp);
3634663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      AMD64AMode* m16_rsp = AMD64AMode_IR(-16, rsp);
3635663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* arg1 is the most significant (Q3), arg4 the least (Q0) */
3636663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* Get all the args into regs, before messing with the stack. */
3637663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      AMD64RI* q3  = iselIntExpr_RI(env, e->Iex.Qop.details->arg1);
3638663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      AMD64RI* q2  = iselIntExpr_RI(env, e->Iex.Qop.details->arg2);
3639663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      AMD64RI* q1  = iselIntExpr_RI(env, e->Iex.Qop.details->arg3);
3640663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      AMD64RI* q0  = iselIntExpr_RI(env, e->Iex.Qop.details->arg4);
3641663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* less significant lane (Q2) at the lower address (-16(rsp)) */
3642663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      addInstr(env, AMD64Instr_Alu64M(Aalu_MOV, q3, m8_rsp));
3643663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      addInstr(env, AMD64Instr_Alu64M(Aalu_MOV, q2, m16_rsp));
3644663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      addInstr(env, AMD64Instr_SseLdSt(True/*load*/, 16, vHi, m16_rsp));
3645663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* and then the lower half .. */
3646663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      addInstr(env, AMD64Instr_Alu64M(Aalu_MOV, q1, m8_rsp));
3647663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      addInstr(env, AMD64Instr_Alu64M(Aalu_MOV, q0, m16_rsp));
3648663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      addInstr(env, AMD64Instr_SseLdSt(True/*load*/, 16, vLo, m16_rsp));
3649663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      *rHi = vHi;
3650663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      *rLo = vLo;
3651663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      return;
3652663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
3653663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3654663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   //avx_fail:
3655663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vex_printf("iselDVecExpr (amd64, subarch = %s): can't reduce\n",
3656663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng              LibVEX_ppVexHwCaps(VexArchAMD64, env->hwcaps));
3657663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   ppIRExpr(e);
3658663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vpanic("iselDVecExpr_wrk");
3659663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
3660663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3661663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3662663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/*---------------------------------------------------------*/
3663ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- ISEL: Statements                                  ---*/
3664ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------*/
3665ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3666ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void iselStmt ( ISelEnv* env, IRStmt* stmt )
3667ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
3668ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (vex_traceflags & VEX_TRACE_VCODE) {
3669ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vex_printf("\n-- ");
3670ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ppIRStmt(stmt);
3671ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vex_printf("\n");
3672ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3673ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3674ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (stmt->tag) {
3675ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3676ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* --------- STORE --------- */
3677ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Ist_Store: {
3678ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRType    tya   = typeOfIRExpr(env->type_env, stmt->Ist.Store.addr);
3679ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRType    tyd   = typeOfIRExpr(env->type_env, stmt->Ist.Store.data);
3680ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IREndness end   = stmt->Ist.Store.end;
3681ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3682ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (tya != Ity_I64 || end != Iend_LE)
3683ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto stmt_fail;
3684ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3685ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (tyd == Ity_I64) {
3686ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         AMD64AMode* am = iselIntExpr_AMode(env, stmt->Ist.Store.addr);
3687ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         AMD64RI* ri = iselIntExpr_RI(env, stmt->Ist.Store.data);
3688ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, AMD64Instr_Alu64M(Aalu_MOV,ri,am));
3689ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
3690ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3691ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (tyd == Ity_I8 || tyd == Ity_I16 || tyd == Ity_I32) {
3692ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         AMD64AMode* am = iselIntExpr_AMode(env, stmt->Ist.Store.addr);
3693ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg r = iselIntExpr_R(env, stmt->Ist.Store.data);
3694ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, AMD64Instr_Store(
3695ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          toUChar(tyd==Ity_I8 ? 1 : (tyd==Ity_I16 ? 2 : 4)),
3696ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          r,am));
3697ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
3698ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3699ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (tyd == Ity_F64) {
3700ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         AMD64AMode* am = iselIntExpr_AMode(env, stmt->Ist.Store.addr);
3701ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg r = iselDblExpr(env, stmt->Ist.Store.data);
3702ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, AMD64Instr_SseLdSt(False/*store*/, 8, r, am));
3703ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
3704ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3705ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (tyd == Ity_F32) {
3706ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         AMD64AMode* am = iselIntExpr_AMode(env, stmt->Ist.Store.addr);
3707ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg r = iselFltExpr(env, stmt->Ist.Store.data);
3708ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, AMD64Instr_SseLdSt(False/*store*/, 4, r, am));
3709ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
3710ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3711ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (tyd == Ity_V128) {
3712ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         AMD64AMode* am = iselIntExpr_AMode(env, stmt->Ist.Store.addr);
3713ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg r = iselVecExpr(env, stmt->Ist.Store.data);
3714ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, AMD64Instr_SseLdSt(False/*store*/, 16, r, am));
3715ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
3716ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3717663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (tyd == Ity_V256) {
3718663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         HReg        rA   = iselIntExpr_R(env, stmt->Ist.Store.addr);
3719663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         AMD64AMode* am0  = AMD64AMode_IR(0,  rA);
3720663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         AMD64AMode* am16 = AMD64AMode_IR(16, rA);
3721663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         HReg vHi, vLo;
3722663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         iselDVecExpr(&vHi, &vLo, env, stmt->Ist.Store.data);
3723663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         addInstr(env, AMD64Instr_SseLdSt(False/*store*/, 16, vLo, am0));
3724663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         addInstr(env, AMD64Instr_SseLdSt(False/*store*/, 16, vHi, am16));
3725663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         return;
3726663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
3727ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
3728ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3729ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3730ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* --------- PUT --------- */
3731ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Ist_Put: {
3732ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRType ty = typeOfIRExpr(env->type_env, stmt->Ist.Put.data);
3733ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (ty == Ity_I64) {
3734ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* We're going to write to memory, so compute the RHS into an
3735ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            AMD64RI. */
3736ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         AMD64RI* ri = iselIntExpr_RI(env, stmt->Ist.Put.data);
3737ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env,
3738ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  AMD64Instr_Alu64M(
3739ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     Aalu_MOV,
3740ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     ri,
3741ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     AMD64AMode_IR(stmt->Ist.Put.offset,
3742ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                   hregAMD64_RBP())
3743ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 ));
3744ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
3745ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3746ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (ty == Ity_I8 || ty == Ity_I16 || ty == Ity_I32) {
3747ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg r = iselIntExpr_R(env, stmt->Ist.Put.data);
3748ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, AMD64Instr_Store(
3749ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          toUChar(ty==Ity_I8 ? 1 : (ty==Ity_I16 ? 2 : 4)),
3750ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          r,
3751ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          AMD64AMode_IR(stmt->Ist.Put.offset,
3752ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                        hregAMD64_RBP())));
3753ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
3754ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3755ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (ty == Ity_F32) {
3756ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg f32 = iselFltExpr(env, stmt->Ist.Put.data);
3757ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         AMD64AMode* am = AMD64AMode_IR(stmt->Ist.Put.offset, hregAMD64_RBP());
3758ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         set_SSE_rounding_default(env); /* paranoia */
3759ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, AMD64Instr_SseLdSt( False/*store*/, 4, f32, am ));
3760ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
3761ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3762ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (ty == Ity_F64) {
3763ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg f64 = iselDblExpr(env, stmt->Ist.Put.data);
3764ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         AMD64AMode* am = AMD64AMode_IR( stmt->Ist.Put.offset,
3765ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                         hregAMD64_RBP() );
3766ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, AMD64Instr_SseLdSt( False/*store*/, 8, f64, am ));
3767ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
3768ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3769663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (ty == Ity_V128) {
3770663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         HReg        vec = iselVecExpr(env, stmt->Ist.Put.data);
3771663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         AMD64AMode* am  = AMD64AMode_IR(stmt->Ist.Put.offset,
3772663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                         hregAMD64_RBP());
3773663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         addInstr(env, AMD64Instr_SseLdSt(False/*store*/, 16, vec, am));
3774663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         return;
3775663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
3776663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (ty == Ity_V256) {
3777663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         HReg vHi, vLo;
3778663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         iselDVecExpr(&vHi, &vLo, env, stmt->Ist.Put.data);
3779663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         HReg        rbp  = hregAMD64_RBP();
3780663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         AMD64AMode* am0  = AMD64AMode_IR(stmt->Ist.Put.offset + 0,  rbp);
3781663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         AMD64AMode* am16 = AMD64AMode_IR(stmt->Ist.Put.offset + 16, rbp);
3782663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         addInstr(env, AMD64Instr_SseLdSt(False/*store*/, 16, vLo, am0));
3783663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         addInstr(env, AMD64Instr_SseLdSt(False/*store*/, 16, vHi, am16));
3784663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         return;
3785663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
3786ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
3787ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3788ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3789ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* --------- Indexed PUT --------- */
3790ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Ist_PutI: {
3791663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      IRPutI *puti = stmt->Ist.PutI.details;
3792663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
3793ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      AMD64AMode* am
3794ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         = genGuestArrayOffset(
3795663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng              env, puti->descr,
3796663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                   puti->ix, puti->bias );
3797ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3798663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      IRType ty = typeOfIRExpr(env->type_env, puti->data);
3799ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (ty == Ity_F64) {
3800663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         HReg val = iselDblExpr(env, puti->data);
3801ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, AMD64Instr_SseLdSt( False/*store*/, 8, val, am ));
3802ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
3803ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3804ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (ty == Ity_I8) {
3805663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         HReg r = iselIntExpr_R(env, puti->data);
3806ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, AMD64Instr_Store( 1, r, am ));
3807ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
3808ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3809ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (ty == Ity_I64) {
3810663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         AMD64RI* ri = iselIntExpr_RI(env, puti->data);
3811ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, AMD64Instr_Alu64M( Aalu_MOV, ri, am ));
3812ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
3813ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3814ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
3815ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3816ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3817ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* --------- TMP --------- */
3818ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Ist_WrTmp: {
3819ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp tmp = stmt->Ist.WrTmp.tmp;
3820ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRType ty = typeOfIRTemp(env->type_env, tmp);
3821ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3822ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* optimisation: if stmt->Ist.WrTmp.data is Add64(..,..),
3823ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         compute it into an AMode and then use LEA.  This usually
3824ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         produces fewer instructions, often because (for memcheck
3825ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         created IR) we get t = address-expression, (t is later used
3826ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         twice) and so doing this naturally turns address-expression
3827ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         back into an AMD64 amode. */
3828ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (ty == Ity_I64
3829ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          && stmt->Ist.WrTmp.data->tag == Iex_Binop
3830ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          && stmt->Ist.WrTmp.data->Iex.Binop.op == Iop_Add64) {
3831ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         AMD64AMode* am = iselIntExpr_AMode(env, stmt->Ist.WrTmp.data);
3832ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg dst = lookupIRTemp(env, tmp);
3833ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (am->tag == Aam_IR && am->Aam.IR.imm == 0) {
3834ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* Hmm, iselIntExpr_AMode wimped out and just computed the
3835ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               value into a register.  Just emit a normal reg-reg move
3836ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               so reg-alloc can coalesce it away in the usual way. */
3837ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HReg src = am->Aam.IR.reg;
3838ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, AMD64Instr_Alu64R(Aalu_MOV, AMD64RMI_Reg(src), dst));
3839ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
3840ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, AMD64Instr_Lea64(am,dst));
3841ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
3842ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
3843ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3844ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3845ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (ty == Ity_I64 || ty == Ity_I32
3846ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          || ty == Ity_I16 || ty == Ity_I8) {
3847ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         AMD64RMI* rmi = iselIntExpr_RMI(env, stmt->Ist.WrTmp.data);
3848ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg dst = lookupIRTemp(env, tmp);
3849ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, AMD64Instr_Alu64R(Aalu_MOV,rmi,dst));
3850ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
3851ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3852ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (ty == Ity_I128) {
3853ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg rHi, rLo, dstHi, dstLo;
3854ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         iselInt128Expr(&rHi,&rLo, env, stmt->Ist.WrTmp.data);
3855663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         lookupIRTempPair( &dstHi, &dstLo, env, tmp);
3856ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, mk_iMOVsd_RR(rHi,dstHi) );
3857ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, mk_iMOVsd_RR(rLo,dstLo) );
3858ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
3859ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3860ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (ty == Ity_I1) {
3861ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         AMD64CondCode cond = iselCondCode(env, stmt->Ist.WrTmp.data);
3862ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg dst = lookupIRTemp(env, tmp);
3863ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, AMD64Instr_Set64(cond, dst));
3864ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
3865ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3866ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (ty == Ity_F64) {
3867ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg dst = lookupIRTemp(env, tmp);
3868ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg src = iselDblExpr(env, stmt->Ist.WrTmp.data);
3869ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, mk_vMOVsd_RR(src, dst));
3870ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
3871ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3872ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (ty == Ity_F32) {
3873ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg dst = lookupIRTemp(env, tmp);
3874ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg src = iselFltExpr(env, stmt->Ist.WrTmp.data);
3875ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, mk_vMOVsd_RR(src, dst));
3876ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
3877ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3878ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (ty == Ity_V128) {
3879ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg dst = lookupIRTemp(env, tmp);
3880ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg src = iselVecExpr(env, stmt->Ist.WrTmp.data);
3881ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, mk_vMOVsd_RR(src, dst));
3882ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
3883ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3884663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (ty == Ity_V256) {
3885663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         HReg rHi, rLo, dstHi, dstLo;
3886663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         iselDVecExpr(&rHi,&rLo, env, stmt->Ist.WrTmp.data);
3887663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         lookupIRTempPair( &dstHi, &dstLo, env, tmp);
3888663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         addInstr(env, mk_vMOVsd_RR(rHi,dstHi) );
3889663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         addInstr(env, mk_vMOVsd_RR(rLo,dstLo) );
3890663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         return;
3891663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
3892ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
3893ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3894ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3895ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* --------- Call to DIRTY helper --------- */
3896ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Ist_Dirty: {
3897ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRType   retty;
3898ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRDirty* d = stmt->Ist.Dirty.details;
3899ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Bool     passBBP = False;
3900ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3901ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (d->nFxState == 0)
3902ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(!d->needsBBP);
3903ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3904ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      passBBP = toBool(d->nFxState > 0 && d->needsBBP);
3905ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3906ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Marshal args, do the call, clear stack. */
3907ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      doHelperCall( env, passBBP, d->guard, d->cee, d->args );
3908ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3909ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Now figure out what to do with the returned value, if any. */
3910ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (d->tmp == IRTemp_INVALID)
3911ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* No return value.  Nothing to do. */
3912ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
3913ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3914ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      retty = typeOfIRTemp(env->type_env, d->tmp);
3915ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (retty == Ity_I64 || retty == Ity_I32
3916ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          || retty == Ity_I16 || retty == Ity_I8) {
3917ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* The returned value is in %rax.  Park it in the register
3918ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            associated with tmp. */
3919ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg dst = lookupIRTemp(env, d->tmp);
3920ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, mk_iMOVsd_RR(hregAMD64_RAX(),dst) );
3921ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
3922ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3923ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
3924ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3925ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3926ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* --------- MEM FENCE --------- */
3927ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Ist_MBE:
3928ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch (stmt->Ist.MBE.event) {
3929ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Imbe_Fence:
3930ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addInstr(env, AMD64Instr_MFence());
3931ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return;
3932ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         default:
3933ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
3934ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3935ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
3936ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3937ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* --------- ACAS --------- */
3938ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Ist_CAS:
3939ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (stmt->Ist.CAS.details->oldHi == IRTemp_INVALID) {
3940ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* "normal" singleton CAS */
3941ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         UChar  sz;
3942ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRCAS* cas = stmt->Ist.CAS.details;
3943ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRType ty  = typeOfIRExpr(env->type_env, cas->dataLo);
3944ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* get: cas->expd into %rax, and cas->data into %rbx */
3945ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         AMD64AMode* am = iselIntExpr_AMode(env, cas->addr);
3946ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg rData = iselIntExpr_R(env, cas->dataLo);
3947ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg rExpd = iselIntExpr_R(env, cas->expdLo);
3948ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg rOld  = lookupIRTemp(env, cas->oldLo);
3949ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(cas->expdHi == NULL);
3950ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(cas->dataHi == NULL);
3951ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, mk_iMOVsd_RR(rExpd, rOld));
3952ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, mk_iMOVsd_RR(rExpd, hregAMD64_RAX()));
3953ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, mk_iMOVsd_RR(rData, hregAMD64_RBX()));
3954ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         switch (ty) {
3955ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Ity_I64: sz = 8; break;
3956ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Ity_I32: sz = 4; break;
3957ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Ity_I16: sz = 2; break;
3958ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Ity_I8:  sz = 1; break;
3959ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            default: goto unhandled_cas;
3960ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
3961ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, AMD64Instr_ACAS(am, sz));
3962ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, AMD64Instr_CMov64(
3963ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          Acc_NZ, AMD64RM_Reg(hregAMD64_RAX()), rOld));
3964ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
3965ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else {
3966ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* double CAS */
3967ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         UChar  sz;
3968ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRCAS* cas = stmt->Ist.CAS.details;
3969ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRType ty  = typeOfIRExpr(env->type_env, cas->dataLo);
3970ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* only 32-bit and 64-bit allowed in this case */
3971ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* get: cas->expdLo into %rax, and cas->dataLo into %rbx */
3972ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* get: cas->expdHi into %rdx, and cas->dataHi into %rcx */
3973ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         AMD64AMode* am = iselIntExpr_AMode(env, cas->addr);
3974ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg rDataHi = iselIntExpr_R(env, cas->dataHi);
3975ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg rDataLo = iselIntExpr_R(env, cas->dataLo);
3976ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg rExpdHi = iselIntExpr_R(env, cas->expdHi);
3977ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg rExpdLo = iselIntExpr_R(env, cas->expdLo);
3978ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg rOldHi  = lookupIRTemp(env, cas->oldHi);
3979ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HReg rOldLo  = lookupIRTemp(env, cas->oldLo);
3980ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         switch (ty) {
3981ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Ity_I64:
3982ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               if (!(env->hwcaps & VEX_HWCAPS_AMD64_CX16))
3983ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  goto unhandled_cas; /* we'd have to generate
3984ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                         cmpxchg16b, but the host
3985ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                         doesn't support that */
3986ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               sz = 8;
3987ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
3988ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case Ity_I32:
3989ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               sz = 4;
3990ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
3991ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            default:
3992ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               goto unhandled_cas;
3993ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
3994ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, mk_iMOVsd_RR(rExpdHi, rOldHi));
3995ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, mk_iMOVsd_RR(rExpdLo, rOldLo));
3996ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, mk_iMOVsd_RR(rExpdHi, hregAMD64_RDX()));
3997ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, mk_iMOVsd_RR(rExpdLo, hregAMD64_RAX()));
3998ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, mk_iMOVsd_RR(rDataHi, hregAMD64_RCX()));
3999ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, mk_iMOVsd_RR(rDataLo, hregAMD64_RBX()));
4000ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env, AMD64Instr_DACAS(am, sz));
4001ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env,
4002ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  AMD64Instr_CMov64(
4003ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     Acc_NZ, AMD64RM_Reg(hregAMD64_RDX()), rOldHi));
4004ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         addInstr(env,
4005ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  AMD64Instr_CMov64(
4006ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     Acc_NZ, AMD64RM_Reg(hregAMD64_RAX()), rOldLo));
4007ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return;
4008ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
4009ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      unhandled_cas:
4010ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
4011ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4012ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* --------- INSTR MARK --------- */
4013ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Doesn't generate any executable code ... */
4014ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Ist_IMark:
4015ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       return;
4016ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4017ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* --------- ABI HINT --------- */
4018ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* These have no meaning (denotation in the IR) and so we ignore
4019ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      them ... if any actually made it this far. */
4020ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Ist_AbiHint:
4021ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       return;
4022ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4023ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* --------- NO-OP --------- */
4024ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Ist_NoOp:
4025ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       return;
4026ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4027ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* --------- EXIT --------- */
4028ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case Ist_Exit: {
4029ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (stmt->Ist.Exit.dst->tag != Ico_U64)
4030ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vpanic("iselStmt(amd64): Ist_Exit: dst is not a 64-bit value");
4031663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
4032663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      AMD64CondCode cc    = iselCondCode(env, stmt->Ist.Exit.guard);
4033663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      AMD64AMode*   amRIP = AMD64AMode_IR(stmt->Ist.Exit.offsIP,
4034663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                          hregAMD64_RBP());
4035663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
4036663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* Case: boring transfer to known address */
4037663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (stmt->Ist.Exit.jk == Ijk_Boring) {
4038663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (env->chainingAllowed) {
4039663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            /* .. almost always true .. */
4040663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            /* Skip the event check at the dst if this is a forwards
4041663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               edge. */
4042663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            Bool toFastEP
4043663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               = ((Addr64)stmt->Ist.Exit.dst->Ico.U64) > env->max_ga;
4044663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            if (0) vex_printf("%s", toFastEP ? "Y" : ",");
4045663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addInstr(env, AMD64Instr_XDirect(stmt->Ist.Exit.dst->Ico.U64,
4046663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                             amRIP, cc, toFastEP));
4047663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         } else {
4048663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            /* .. very occasionally .. */
4049663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            /* We can't use chaining, so ask for an assisted transfer,
4050663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               as that's the only alternative that is allowable. */
4051663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            HReg r = iselIntExpr_R(env, IRExpr_Const(stmt->Ist.Exit.dst));
4052663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addInstr(env, AMD64Instr_XAssisted(r, amRIP, cc, Ijk_Boring));
4053663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
4054663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         return;
4055663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
4056663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
4057663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* Case: assisted transfer to arbitrary address */
4058663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      switch (stmt->Ist.Exit.jk) {
4059663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* Keep this list in sync with that in iselNext below */
4060663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case Ijk_ClientReq:
4061663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case Ijk_EmWarn:
4062663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case Ijk_NoDecode:
4063663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case Ijk_NoRedir:
4064663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case Ijk_SigSEGV:
4065663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case Ijk_SigTRAP:
4066663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case Ijk_Sys_syscall:
4067663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case Ijk_TInval:
4068663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case Ijk_Yield:
4069663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         {
4070663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            HReg r = iselIntExpr_R(env, IRExpr_Const(stmt->Ist.Exit.dst));
4071663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addInstr(env, AMD64Instr_XAssisted(r, amRIP, cc, stmt->Ist.Exit.jk));
4072663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            return;
4073663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
4074663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         default:
4075663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            break;
4076663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
4077663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
4078663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* Do we ever expect to see any other kind? */
4079663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      goto stmt_fail;
4080ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
4081ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4082ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   default: break;
4083ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
4084ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  stmt_fail:
4085ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ppIRStmt(stmt);
4086ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vpanic("iselStmt(amd64)");
4087ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4088ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4089ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4090ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------*/
4091ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- ISEL: Basic block terminators (Nexts)             ---*/
4092ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------*/
4093ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4094663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic void iselNext ( ISelEnv* env,
4095663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                       IRExpr* next, IRJumpKind jk, Int offsIP )
4096ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
4097ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (vex_traceflags & VEX_TRACE_VCODE) {
4098663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      vex_printf( "\n-- PUT(%d) = ", offsIP);
4099663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      ppIRExpr( next );
4100663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      vex_printf( "; exit-");
4101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ppIRJumpKind(jk);
4102663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      vex_printf( "\n");
4103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
4104663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
4105663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* Case: boring transfer to known address */
4106663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (next->tag == Iex_Const) {
4107663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      IRConst* cdst = next->Iex.Const.con;
4108663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      vassert(cdst->tag == Ico_U64);
4109663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (jk == Ijk_Boring || jk == Ijk_Call) {
4110663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* Boring transfer to known address */
4111663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         AMD64AMode* amRIP = AMD64AMode_IR(offsIP, hregAMD64_RBP());
4112663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (env->chainingAllowed) {
4113663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            /* .. almost always true .. */
4114663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            /* Skip the event check at the dst if this is a forwards
4115663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               edge. */
4116663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            Bool toFastEP
4117663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               = ((Addr64)cdst->Ico.U64) > env->max_ga;
4118663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            if (0) vex_printf("%s", toFastEP ? "X" : ".");
4119663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addInstr(env, AMD64Instr_XDirect(cdst->Ico.U64,
4120663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                             amRIP, Acc_ALWAYS,
4121663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                             toFastEP));
4122663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         } else {
4123663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            /* .. very occasionally .. */
4124663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            /* We can't use chaining, so ask for an indirect transfer,
4125663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               as that's the cheapest alternative that is
4126663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               allowable. */
4127663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            HReg r = iselIntExpr_R(env, next);
4128663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addInstr(env, AMD64Instr_XAssisted(r, amRIP, Acc_ALWAYS,
4129663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                               Ijk_Boring));
4130663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
4131663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         return;
4132663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
4133663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
4134663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
4135663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* Case: call/return (==boring) transfer to any address */
4136663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   switch (jk) {
4137663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Ijk_Boring: case Ijk_Ret: case Ijk_Call: {
4138663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         HReg        r     = iselIntExpr_R(env, next);
4139663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         AMD64AMode* amRIP = AMD64AMode_IR(offsIP, hregAMD64_RBP());
4140663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (env->chainingAllowed) {
4141663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addInstr(env, AMD64Instr_XIndir(r, amRIP, Acc_ALWAYS));
4142663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         } else {
4143663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            addInstr(env, AMD64Instr_XAssisted(r, amRIP, Acc_ALWAYS,
4144663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                               Ijk_Boring));
4145663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
4146663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         return;
4147663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
4148663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      default:
4149663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         break;
4150663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
4151663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
4152663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* Case: assisted transfer to arbitrary address */
4153663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   switch (jk) {
4154663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* Keep this list in sync with that for Ist_Exit above */
4155663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Ijk_ClientReq:
4156663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Ijk_EmWarn:
4157663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Ijk_NoDecode:
4158663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Ijk_NoRedir:
4159663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Ijk_SigSEGV:
4160663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Ijk_SigTRAP:
4161663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Ijk_Sys_syscall:
4162663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Ijk_TInval:
4163663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Ijk_Yield: {
4164663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         HReg        r     = iselIntExpr_R(env, next);
4165663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         AMD64AMode* amRIP = AMD64AMode_IR(offsIP, hregAMD64_RBP());
4166663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         addInstr(env, AMD64Instr_XAssisted(r, amRIP, Acc_ALWAYS, jk));
4167663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         return;
4168663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
4169663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      default:
4170663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         break;
4171663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
4172663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
4173663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vex_printf( "\n-- PUT(%d) = ", offsIP);
4174663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   ppIRExpr( next );
4175663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vex_printf( "; exit-");
4176663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   ppIRJumpKind(jk);
4177663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vex_printf( "\n");
4178663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vassert(0); // are we expecting any other kind?
4179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------*/
4183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Insn selector top-level                           ---*/
4184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------*/
4185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Translate an entire SB to amd64 code. */
4187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4188663860b1408516d02ebfcb3a9999a134e6cfb223Ben ChengHInstrArray* iselSB_AMD64 ( IRSB* bb,
4189663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                            VexArch      arch_host,
4190663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                            VexArchInfo* archinfo_host,
4191663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                            VexAbiInfo*  vbi/*UNUSED*/,
4192663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                            Int offs_Host_EvC_Counter,
4193663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                            Int offs_Host_EvC_FailAddr,
4194663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                            Bool chainingAllowed,
4195663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                            Bool addProfInc,
4196663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                            Addr64 max_ga )
4197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
4198663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   Int        i, j;
4199663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   HReg       hreg, hregHI;
4200663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   ISelEnv*   env;
4201663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UInt       hwcaps_host = archinfo_host->hwcaps;
4202663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   AMD64AMode *amCounter, *amFailAddr;
4203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* sanity ... */
4205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(arch_host == VexArchAMD64);
4206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(0 == (hwcaps_host
4207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 & ~(VEX_HWCAPS_AMD64_SSE3
4208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     | VEX_HWCAPS_AMD64_CX16
4209663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                     | VEX_HWCAPS_AMD64_LZCNT
4210663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                     | VEX_HWCAPS_AMD64_AVX)));
4211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Make up an initial environment to use. */
4213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   env = LibVEX_Alloc(sizeof(ISelEnv));
4214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   env->vreg_ctr = 0;
4215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Set up output code array. */
4217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   env->code = newHInstrArray();
4218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Copy BB's type env. */
4220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   env->type_env = bb->tyenv;
4221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Make up an IRTemp -> virtual HReg mapping.  This doesn't
4223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      change as we go along. */
4224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   env->n_vregmap = bb->tyenv->types_used;
4225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   env->vregmap   = LibVEX_Alloc(env->n_vregmap * sizeof(HReg));
4226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   env->vregmapHI = LibVEX_Alloc(env->n_vregmap * sizeof(HReg));
4227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* and finally ... */
4229663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   env->chainingAllowed = chainingAllowed;
4230663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   env->hwcaps          = hwcaps_host;
4231663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   env->max_ga          = max_ga;
4232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* For each IR temporary, allocate a suitably-kinded virtual
4234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      register. */
4235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   j = 0;
4236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (i = 0; i < env->n_vregmap; i++) {
4237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      hregHI = hreg = INVALID_HREG;
4238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch (bb->tyenv->types[i]) {
4239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Ity_I1:
4240663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case Ity_I8: case Ity_I16: case Ity_I32: case Ity_I64:
4241663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            hreg = mkHReg(j++, HRcInt64, True);
4242663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            break;
4243663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case Ity_I128:
4244663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            hreg   = mkHReg(j++, HRcInt64, True);
4245663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            hregHI = mkHReg(j++, HRcInt64, True);
4246663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            break;
4247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Ity_F32:
4248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Ity_F64:
4249663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case Ity_V128:
4250663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            hreg = mkHReg(j++, HRcVec128, True);
4251663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            break;
4252663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case Ity_V256:
4253663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            hreg   = mkHReg(j++, HRcVec128, True);
4254663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            hregHI = mkHReg(j++, HRcVec128, True);
4255663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            break;
4256663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         default:
4257663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            ppIRType(bb->tyenv->types[i]);
4258663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            vpanic("iselBB(amd64): IRTemp type");
4259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
4260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      env->vregmap[i]   = hreg;
4261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      env->vregmapHI[i] = hregHI;
4262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
4263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   env->vreg_ctr = j;
4264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4265663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* The very first instruction must be an event check. */
4266663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   amCounter  = AMD64AMode_IR(offs_Host_EvC_Counter,  hregAMD64_RBP());
4267663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   amFailAddr = AMD64AMode_IR(offs_Host_EvC_FailAddr, hregAMD64_RBP());
4268663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   addInstr(env, AMD64Instr_EvCheck(amCounter, amFailAddr));
4269663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
4270663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* Possibly a block counter increment (for profiling).  At this
4271663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      point we don't know the address of the counter, so just pretend
4272663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      it is zero.  It will have to be patched later, but before this
4273663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      translation is used, by a call to LibVEX_patchProfCtr. */
4274663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (addProfInc) {
4275663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      addInstr(env, AMD64Instr_ProfInc());
4276663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
4277663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
4278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Ok, finally we can iterate over the statements. */
4279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (i = 0; i < bb->stmts_used; i++)
4280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (bb->stmts[i])
4281663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         iselStmt(env, bb->stmts[i]);
4282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4283663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   iselNext(env, bb->next, bb->jumpkind, bb->offsIP);
4284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* record the number of vregs we used. */
4286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   env->code->n_vregs = env->vreg_ctr;
4287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return env->code;
4288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------------*/
4292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- end                                   host_amd64_isel.c ---*/
4293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------------*/
4294