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