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