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