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 10436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov Copyright (C) 2004-2013 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" 46436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#include "host_generic_simd256.h" 47436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#include "host_generic_maddf.h" 48ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "host_amd64_defs.h" 49ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 50ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 51ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------*/ 52ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- x87/SSE control word stuff ---*/ 53ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------*/ 54ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 55ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Vex-generated code expects to run with the FPU set as follows: all 56ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown exceptions masked, round-to-nearest, precision = 53 bits. This 57ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown corresponds to a FPU control word value of 0x027F. 58ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 59ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Similarly the SSE control word (%mxcsr) should be 0x1F80. 60ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 61ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown %fpucw and %mxcsr should have these values on entry to 62ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Vex-generated code, and should those values should be 63ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown unchanged at exit. 64ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/ 65ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 66ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define DEFAULT_FPUCW 0x027F 67ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 68ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define DEFAULT_MXCSR 0x1F80 69ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 70ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* debugging only, do not use */ 71ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* define DEFAULT_FPUCW 0x037F */ 72ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 73ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 74ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------*/ 75ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- misc helpers ---*/ 76ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------*/ 77ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 78ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* These are duplicated in guest-amd64/toIR.c */ 79ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRExpr* unop ( IROp op, IRExpr* a ) 80ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 81ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return IRExpr_Unop(op, a); 82ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 83ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 84ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRExpr* binop ( IROp op, IRExpr* a1, IRExpr* a2 ) 85ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 86ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return IRExpr_Binop(op, a1, a2); 87ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 88ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 89ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRExpr* bind ( Int binder ) 90ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 91ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return IRExpr_Binder(binder); 92ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 93ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 94436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstatic Bool isZeroU8 ( IRExpr* e ) 95436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov{ 96436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov return e->tag == Iex_Const 97436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov && e->Iex.Const.con->tag == Ico_U8 98436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov && e->Iex.Const.con->Ico.U8 == 0; 99436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov} 100436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------*/ 103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- ISelEnv ---*/ 104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------*/ 105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* This carries around: 107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown - A mapping from IRTemp to IRType, giving the type of any IRTemp we 109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown might encounter. This is computed before insn selection starts, 110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown and does not change. 111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown - A mapping from IRTemp to HReg. This tells the insn selector 113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown which virtual register is associated with each IRTemp 114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown temporary. This is computed before insn selection starts, and 115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown does not change. We expect this mapping to map precisely the 116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown same set of IRTemps as the type mapping does. 117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown - vregmap holds the primary register for the IRTemp. 119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown - vregmapHI is only used for 128-bit integer-typed 120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRTemps. It holds the identity of a second 121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 64-bit virtual HReg, which holds the high half 122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown of the value. 123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 124663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng - The host subarchitecture we are selecting insns for. 125663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng This is set at the start and does not change. 126663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown - The code array, that is, the insns selected so far. 128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown - A counter, for generating new virtual registers. 130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 131663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng - A Bool for indicating whether we may generate chain-me 132663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng instructions for control flow transfers, or whether we must use 133663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng XAssisted. 134663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 135663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng - The maximum guest address of any guest insn in this block. 136663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng Actually, the address of the highest-addressed byte from any insn 137663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng in this block. Is set at the start and does not change. This is 138663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng used for detecting jumps which are definitely forward-edges from 139663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng this block, and therefore can be made (chained) to the fast entry 140663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng point of the destination, thereby avoiding the destination's 141663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng event check. 142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Note, this is all host-independent. (JRS 20050201: well, kinda 144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ... not completely. Compare with ISelEnv for X86.) 145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/ 146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef 148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown struct { 149663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng /* Constant -- are set at the start and do not change. */ 150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRTypeEnv* type_env; 151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg* vregmap; 153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg* vregmapHI; 154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int n_vregmap; 155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 156663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng UInt hwcaps; 157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 158663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng Bool chainingAllowed; 159663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng Addr64 max_ga; 160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 161663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng /* These are modified as we go along. */ 162663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng HInstrArray* code; 163663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng Int vreg_ctr; 164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ISelEnv; 166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic HReg lookupIRTemp ( ISelEnv* env, IRTemp tmp ) 169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert(tmp >= 0); 171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert(tmp < env->n_vregmap); 172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return env->vregmap[tmp]; 173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 175663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic void lookupIRTempPair ( HReg* vrHI, HReg* vrLO, 176663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng ISelEnv* env, IRTemp tmp ) 177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert(tmp >= 0); 179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert(tmp < env->n_vregmap); 180436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov vassert(! hregIsInvalid(env->vregmapHI[tmp])); 181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *vrLO = env->vregmap[tmp]; 182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *vrHI = env->vregmapHI[tmp]; 183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void addInstr ( ISelEnv* env, AMD64Instr* instr ) 186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addHInstr(env->code, instr); 188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (vex_traceflags & VEX_TRACE_VCODE) { 189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ppAMD64Instr(instr, True); 190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vex_printf("\n"); 191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic HReg newVRegI ( ISelEnv* env ) 195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg reg = mkHReg(env->vreg_ctr, HRcInt64, True/*virtual reg*/); 197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown env->vreg_ctr++; 198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return reg; 199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic HReg newVRegV ( ISelEnv* env ) 202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg reg = mkHReg(env->vreg_ctr, HRcVec128, True/*virtual reg*/); 204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown env->vreg_ctr++; 205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return reg; 206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------*/ 210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- ISEL: Forward declarations ---*/ 211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------*/ 212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* These are organised as iselXXX and iselXXX_wrk pairs. The 214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown iselXXX_wrk do the real work, but are not to be called directly. 215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown For each XXX, iselXXX calls its iselXXX_wrk counterpart, then 216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown checks that all returned registers are virtual. You should not 217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown call the _wrk version directly. 218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/ 219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic AMD64RMI* iselIntExpr_RMI_wrk ( ISelEnv* env, IRExpr* e ); 220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic AMD64RMI* iselIntExpr_RMI ( ISelEnv* env, IRExpr* e ); 221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic AMD64RI* iselIntExpr_RI_wrk ( ISelEnv* env, IRExpr* e ); 223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic AMD64RI* iselIntExpr_RI ( ISelEnv* env, IRExpr* e ); 224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic AMD64RM* iselIntExpr_RM_wrk ( ISelEnv* env, IRExpr* e ); 226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic AMD64RM* iselIntExpr_RM ( ISelEnv* env, IRExpr* e ); 227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic HReg iselIntExpr_R_wrk ( ISelEnv* env, IRExpr* e ); 229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic HReg iselIntExpr_R ( ISelEnv* env, IRExpr* e ); 230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic AMD64AMode* iselIntExpr_AMode_wrk ( ISelEnv* env, IRExpr* e ); 232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic AMD64AMode* iselIntExpr_AMode ( ISelEnv* env, IRExpr* e ); 233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 234663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic void iselInt128Expr_wrk ( /*OUT*/HReg* rHi, HReg* rLo, 235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ISelEnv* env, IRExpr* e ); 236663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic void iselInt128Expr ( /*OUT*/HReg* rHi, HReg* rLo, 237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ISelEnv* env, IRExpr* e ); 238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic AMD64CondCode iselCondCode_wrk ( ISelEnv* env, IRExpr* e ); 240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic AMD64CondCode iselCondCode ( ISelEnv* env, IRExpr* e ); 241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic HReg iselDblExpr_wrk ( ISelEnv* env, IRExpr* e ); 243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic HReg iselDblExpr ( ISelEnv* env, IRExpr* e ); 244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic HReg iselFltExpr_wrk ( ISelEnv* env, IRExpr* e ); 246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic HReg iselFltExpr ( ISelEnv* env, IRExpr* e ); 247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic HReg iselVecExpr_wrk ( ISelEnv* env, IRExpr* e ); 249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic HReg iselVecExpr ( ISelEnv* env, IRExpr* e ); 250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 251663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic void iselDVecExpr_wrk ( /*OUT*/HReg* rHi, HReg* rLo, 252663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng ISelEnv* env, IRExpr* e ); 253663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic void iselDVecExpr ( /*OUT*/HReg* rHi, HReg* rLo, 254663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng ISelEnv* env, IRExpr* e ); 255663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------*/ 258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- ISEL: Misc helpers ---*/ 259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------*/ 260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool sane_AMode ( AMD64AMode* am ) 262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (am->tag) { 264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Aam_IR: 265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return 266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown toBool( hregClass(am->Aam.IR.reg) == HRcInt64 267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && (hregIsVirtual(am->Aam.IR.reg) 268436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov || sameHReg(am->Aam.IR.reg, hregAMD64_RBP())) ); 269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Aam_IRRS: 270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return 271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown toBool( hregClass(am->Aam.IRRS.base) == HRcInt64 272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && hregIsVirtual(am->Aam.IRRS.base) 273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && hregClass(am->Aam.IRRS.index) == HRcInt64 274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && hregIsVirtual(am->Aam.IRRS.index) ); 275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: 276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vpanic("sane_AMode: unknown amd64 amode tag"); 277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Can the lower 32 bits be signedly widened to produce the whole 282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 64-bit value? In other words, are the top 33 bits either all 0 or 283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown all 1 ? */ 284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool fitsIn32Bits ( ULong x ) 285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Long y0 = (Long)x; 287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Long y1 = y0; 288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown y1 <<= 32; 289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown y1 >>=/*s*/ 32; 290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return toBool(x == y1); 291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Is this a 64-bit zero expression? */ 294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool isZeroU64 ( IRExpr* e ) 296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return e->tag == Iex_Const 298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && e->Iex.Const.con->tag == Ico_U64 299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && e->Iex.Const.con->Ico.U64 == 0ULL; 300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool isZeroU32 ( IRExpr* e ) 303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return e->tag == Iex_Const 305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && e->Iex.Const.con->tag == Ico_U32 306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && e->Iex.Const.con->Ico.U32 == 0; 307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Make a int reg-reg move. */ 310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic AMD64Instr* mk_iMOVsd_RR ( HReg src, HReg dst ) 312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert(hregClass(src) == HRcInt64); 314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert(hregClass(dst) == HRcInt64); 315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return AMD64Instr_Alu64R(Aalu_MOV, AMD64RMI_Reg(src), dst); 316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 318663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* Make a vector (128 bit) reg-reg move. */ 319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic AMD64Instr* mk_vMOVsd_RR ( HReg src, HReg dst ) 321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert(hregClass(src) == HRcVec128); 323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert(hregClass(dst) == HRcVec128); 324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return AMD64Instr_SseReRg(Asse_MOV, src, dst); 325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Advance/retreat %rsp by n. */ 328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void add_to_rsp ( ISelEnv* env, Int n ) 330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert(n > 0 && n < 256 && (n%8) == 0); 332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, 333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown AMD64Instr_Alu64R(Aalu_ADD, AMD64RMI_Imm(n), 334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown hregAMD64_RSP())); 335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void sub_from_rsp ( ISelEnv* env, Int n ) 338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert(n > 0 && n < 256 && (n%8) == 0); 340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, 341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown AMD64Instr_Alu64R(Aalu_SUB, AMD64RMI_Imm(n), 342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown hregAMD64_RSP())); 343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Push 64-bit constants on the stack. */ 346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void push_uimm64( ISelEnv* env, ULong uimm64 ) 347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* If uimm64 can be expressed as the sign extension of its 349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown lower 32 bits, we can do it the easy way. */ 350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Long simm64 = (Long)uimm64; 351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if ( simm64 == ((simm64 << 32) >> 32) ) { 352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr( env, AMD64Instr_Push(AMD64RMI_Imm( (UInt)uimm64 )) ); 353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg tmp = newVRegI(env); 355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr( env, AMD64Instr_Imm64(uimm64, tmp) ); 356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr( env, AMD64Instr_Push(AMD64RMI_Reg(tmp)) ); 357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Used only in doHelperCall. If possible, produce a single 362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown instruction which computes 'e' into 'dst'. If not possible, return 363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown NULL. */ 364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic AMD64Instr* iselIntExpr_single_instruction ( ISelEnv* env, 366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg dst, 367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRExpr* e ) 368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 369436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /* Per comments in doHelperCall below, appearance of 370436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov Iex_VECRET implies ill-formed IR. */ 371436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov vassert(e->tag != Iex_VECRET); 372436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 373436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /* In this case we give out a copy of the BaseBlock pointer. */ 374436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov if (UNLIKELY(e->tag == Iex_BBPTR)) { 375436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov return mk_iMOVsd_RR( hregAMD64_RBP(), dst ); 376436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } 377436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert(typeOfIRExpr(env->type_env, e) == Ity_I64); 379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->tag == Iex_Const) { 381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert(e->Iex.Const.con->tag == Ico_U64); 382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (fitsIn32Bits(e->Iex.Const.con->Ico.U64)) { 383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return AMD64Instr_Alu64R( 384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Aalu_MOV, 385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown AMD64RMI_Imm(toUInt(e->Iex.Const.con->Ico.U64)), 386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown dst 387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ); 388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return AMD64Instr_Imm64(e->Iex.Const.con->Ico.U64, dst); 390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->tag == Iex_RdTmp) { 394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg src = lookupIRTemp(env, e->Iex.RdTmp.tmp); 395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return mk_iMOVsd_RR(src, dst); 396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->tag == Iex_Get) { 399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert(e->Iex.Get.ty == Ity_I64); 400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return AMD64Instr_Alu64R( 401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Aalu_MOV, 402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown AMD64RMI_Mem( 403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown AMD64AMode_IR(e->Iex.Get.offset, 404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown hregAMD64_RBP())), 405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown dst); 406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->tag == Iex_Unop 409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && e->Iex.Unop.op == Iop_32Uto64 410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && e->Iex.Unop.arg->tag == Iex_RdTmp) { 411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg src = lookupIRTemp(env, e->Iex.Unop.arg->Iex.RdTmp.tmp); 412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return AMD64Instr_MovxLQ(False, src, dst); 413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (0) { ppIRExpr(e); vex_printf("\n"); } 416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return NULL; 418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 421436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov/* Do a complete function call. |guard| is a Ity_Bit expression 422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown indicating whether or not the call happens. If guard==NULL, the 423436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov call is unconditional. |retloc| is set to indicate where the 424436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov return value is after the call. The caller (of this fn) must 425436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov generate code to add |stackAdjustAfterCall| to the stack pointer 426436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov after the call is done. */ 427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic 429436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovvoid doHelperCall ( /*OUT*/UInt* stackAdjustAfterCall, 430436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /*OUT*/RetLoc* retloc, 431436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov ISelEnv* env, 432436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov IRExpr* guard, 433436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov IRCallee* cee, IRType retTy, IRExpr** args ) 434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown AMD64CondCode cc; 436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argregs[6]; 437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg tmpregs[6]; 438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown AMD64Instr* fastinstrs[6]; 439436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov UInt n_args, i; 440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 441436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /* Set default returns. We'll update them later if needed. */ 442436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov *stackAdjustAfterCall = 0; 443436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov *retloc = mk_RetLoc_INVALID(); 444436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 445436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /* These are used for cross-checking that IR-level constraints on 446436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov the use of IRExpr_VECRET() and IRExpr_BBPTR() are observed. */ 447436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov UInt nVECRETs = 0; 448436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov UInt nBBPTRs = 0; 449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 450436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /* Marshal args for a call and do the call. 451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown This function only deals with a tiny set of possibilities, which 453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown cover all helpers in practice. The restrictions are that only 454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown arguments in registers are supported, hence only 6x64 integer 455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown bits in total can be passed. In fact the only supported arg 456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown type is I64. 457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 458436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov The return type can be I{64,32,16,8} or V{128,256}. In the 459436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov latter two cases, it is expected that |args| will contain the 460436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov special node IRExpr_VECRET(), in which case this routine 461436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov generates code to allocate space on the stack for the vector 462436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov return value. Since we are not passing any scalars on the 463436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov stack, it is enough to preallocate the return space before 464436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov marshalling any arguments, in this case. 465436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 466436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov |args| may also contain IRExpr_BBPTR(), in which case the 467436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov value in %rbp is passed as the corresponding argument. 468436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Generating code which is both efficient and correct when 470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown parameters are to be passed in registers is difficult, for the 471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown reasons elaborated in detail in comments attached to 472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown doHelperCall() in priv/host-x86/isel.c. Here, we use a variant 473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown of the method described in those comments. 474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown The problem is split into two cases: the fast scheme and the 476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown slow scheme. In the fast scheme, arguments are computed 477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown directly into the target (real) registers. This is only safe 478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown when we can be sure that computation of each argument will not 479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown trash any real registers set by computation of any other 480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown argument. 481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown In the slow scheme, all args are first computed into vregs, and 483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown once they are all done, they are moved to the relevant real 484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown regs. This always gives correct code, but it also gives a bunch 485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown of vreg-to-rreg moves which are usually redundant but are hard 486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for the register allocator to get rid of. 487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown To decide which scheme to use, all argument expressions are 489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown first examined. If they are all so simple that it is clear they 490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown will be evaluated without use of any fixed registers, use the 491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fast scheme, else use the slow scheme. Note also that only 492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown unconditional calls may use the fast scheme, since having to 493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown compute a condition expression could itself trash real 494436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov registers. Note that for simplicity, in the case where 495436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov IRExpr_VECRET() is present, we use the slow scheme. This is 496436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov motivated by the desire to avoid any possible complexity 497436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov w.r.t. nested calls. 498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Note this requires being able to examine an expression and 500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown determine whether or not evaluation of it might use a fixed 501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown register. That requires knowledge of how the rest of this insn 502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown selector works. Currently just the following 3 are regarded as 503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown safe -- hopefully they cover the majority of arguments in 504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown practice: IRExpr_Tmp IRExpr_Const IRExpr_Get. 505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */ 506ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 507ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Note that the cee->regparms field is meaningless on AMD64 host 508ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (since there is only one calling convention) and so we always 509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ignore it. */ 510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown n_args = 0; 511ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (i = 0; args[i]; i++) 512ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown n_args++; 513ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 514436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov if (n_args > 6) 515ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vpanic("doHelperCall(AMD64): cannot currently handle > 6 args"); 516ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 517ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown argregs[0] = hregAMD64_RDI(); 518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown argregs[1] = hregAMD64_RSI(); 519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown argregs[2] = hregAMD64_RDX(); 520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown argregs[3] = hregAMD64_RCX(); 521ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown argregs[4] = hregAMD64_R8(); 522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown argregs[5] = hregAMD64_R9(); 523ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 524ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tmpregs[0] = tmpregs[1] = tmpregs[2] = 525ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tmpregs[3] = tmpregs[4] = tmpregs[5] = INVALID_HREG; 526ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 527ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fastinstrs[0] = fastinstrs[1] = fastinstrs[2] = 528ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fastinstrs[3] = fastinstrs[4] = fastinstrs[5] = NULL; 529ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 530ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* First decide which scheme (slow or fast) is to be used. First 531ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown assume the fast scheme, and select slow if any contraindications 532ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (wow) appear. */ 533ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 534436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /* We'll need space on the stack for the return value. Avoid 535436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov possible complications with nested calls by using the slow 536436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov scheme. */ 537436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov if (retTy == Ity_V128 || retTy == Ity_V256) 538436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov goto slowscheme; 539436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 540ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (guard) { 541ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (guard->tag == Iex_Const 542ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && guard->Iex.Const.con->tag == Ico_U1 543ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && guard->Iex.Const.con->Ico.U1 == True) { 544ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* unconditional */ 545ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 546ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Not manifestly unconditional -- be conservative. */ 547ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown goto slowscheme; 548ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 549ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 550ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 551ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Ok, let's try for the fast scheme. If it doesn't pan out, we'll 552ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown use the slow scheme. Because this is tentative, we can't call 553ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr (that is, commit to) any instructions until we're 554ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown handled all the arguments. So park the resulting instructions 555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown in a buffer and emit that if we're successful. */ 556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* FAST SCHEME */ 558436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /* In this loop, we process args that can be computed into the 559436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov destination (real) register with a single instruction, without 560436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov using any fixed regs. That also includes IRExpr_BBPTR(), but 561436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov not IRExpr_VECRET(). Indeed, if the IR is well-formed, we can 562436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov never see IRExpr_VECRET() at this point, since the return-type 563436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov check above should ensure all those cases use the slow scheme 564436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov instead. */ 565436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov vassert(n_args >= 0 && n_args <= 6); 566ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (i = 0; i < n_args; i++) { 567436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov IRExpr* arg = args[i]; 568436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov if (LIKELY(!is_IRExpr_VECRET_or_BBPTR(arg))) { 569436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov vassert(typeOfIRExpr(env->type_env, args[i]) == Ity_I64); 570436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } 571436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov fastinstrs[i] 572436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov = iselIntExpr_single_instruction( env, argregs[i], args[i] ); 573436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov if (fastinstrs[i] == NULL) 574ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown goto slowscheme; 575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Looks like we're in luck. Emit the accumulated instructions and 578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown move on to doing the call itself. */ 579436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov for (i = 0; i < n_args; i++) 580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, fastinstrs[i]); 581ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 582ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Fast scheme only applies for unconditional calls. Hence: */ 583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown cc = Acc_ALWAYS; 584ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown goto handle_call; 586ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 587ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* SLOW SCHEME; move via temporaries */ 589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown slowscheme: 590436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov {} 591663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng# if 0 /* debug only */ 592663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng if (n_args > 0) {for (i = 0; args[i]; i++) { 593663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng ppIRExpr(args[i]); vex_printf(" "); } 594663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng vex_printf("\n");} 595663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng# endif 596436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 597436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /* If we have a vector return type, allocate a place for it on the 598436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov stack and record its address. */ 599436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov HReg r_vecRetAddr = INVALID_HREG; 600436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov if (retTy == Ity_V128) { 601436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov r_vecRetAddr = newVRegI(env); 602436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov sub_from_rsp(env, 16); 603436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov addInstr(env, mk_iMOVsd_RR( hregAMD64_RSP(), r_vecRetAddr )); 604436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } 605436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov else if (retTy == Ity_V256) { 606436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov r_vecRetAddr = newVRegI(env); 607436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov sub_from_rsp(env, 32); 608436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov addInstr(env, mk_iMOVsd_RR( hregAMD64_RSP(), r_vecRetAddr )); 609ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 610ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 611436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov vassert(n_args >= 0 && n_args <= 6); 612ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (i = 0; i < n_args; i++) { 613436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov IRExpr* arg = args[i]; 614436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov if (UNLIKELY(arg->tag == Iex_BBPTR)) { 615436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov tmpregs[i] = newVRegI(env); 616436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov addInstr(env, mk_iMOVsd_RR( hregAMD64_RBP(), tmpregs[i])); 617436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov nBBPTRs++; 618436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } 619436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov else if (UNLIKELY(arg->tag == Iex_VECRET)) { 620436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /* We stashed the address of the return slot earlier, so just 621436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov retrieve it now. */ 622436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov vassert(!hregIsInvalid(r_vecRetAddr)); 623436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov tmpregs[i] = r_vecRetAddr; 624436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov nVECRETs++; 625436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } 626436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov else { 627436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov vassert(typeOfIRExpr(env->type_env, args[i]) == Ity_I64); 628436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov tmpregs[i] = iselIntExpr_R(env, args[i]); 629436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } 630ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Now we can compute the condition. We can't do it earlier 633ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown because the argument computations could trash the condition 634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown codes. Be a bit clever to handle the common case where the 635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown guard is 1:Bit. */ 636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown cc = Acc_ALWAYS; 637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (guard) { 638ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (guard->tag == Iex_Const 639ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && guard->Iex.Const.con->tag == Ico_U1 640ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && guard->Iex.Const.con->Ico.U1 == True) { 641ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* unconditional -- do nothing */ 642ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 643ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown cc = iselCondCode( env, guard ); 644ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 645ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 646ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 647ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Move the args to their final destinations. */ 648436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov for (i = 0; i < n_args; i++) { 649ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* None of these insns, including any spill code that might 650ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown be generated, may alter the condition codes. */ 651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr( env, mk_iMOVsd_RR( tmpregs[i], argregs[i] ) ); 652ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 653ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 654ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 655436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /* Do final checks, set the return values, and generate the call 656436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov instruction proper. */ 657ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown handle_call: 658436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 659436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov if (retTy == Ity_V128 || retTy == Ity_V256) { 660436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov vassert(nVECRETs == 1); 661436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } else { 662436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov vassert(nVECRETs == 0); 663436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } 664436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 665436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov vassert(nBBPTRs == 0 || nBBPTRs == 1); 666436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 667436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov vassert(*stackAdjustAfterCall == 0); 668436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov vassert(is_RetLoc_INVALID(*retloc)); 669436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov switch (retTy) { 670436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case Ity_INVALID: 671436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /* Function doesn't return a value. */ 672436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov *retloc = mk_RetLoc_simple(RLPri_None); 673436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov break; 674436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case Ity_I64: case Ity_I32: case Ity_I16: case Ity_I8: 675436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov *retloc = mk_RetLoc_simple(RLPri_Int); 676436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov break; 677436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case Ity_V128: 678436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov *retloc = mk_RetLoc_spRel(RLPri_V128SpRel, 0); 679436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov *stackAdjustAfterCall = 16; 680436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov break; 681436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case Ity_V256: 682436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov *retloc = mk_RetLoc_spRel(RLPri_V256SpRel, 0); 683436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov *stackAdjustAfterCall = 32; 684436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov break; 685436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov default: 686436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /* IR can denote other possible return types, but we don't 687436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov handle those here. */ 688436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov vassert(0); 689436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } 690436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 691436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /* Finally, generate the call itself. This needs the *retloc value 692436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov set in the switch above, which is why it's at the end. */ 693436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov addInstr(env, 694436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov AMD64Instr_Call(cc, Ptr_to_ULong(cee->addr), n_args, *retloc)); 695ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 696ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 697ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 698ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Given a guest-state array descriptor, an index expression and a 699ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown bias, generate an AMD64AMode holding the relevant guest state 700ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown offset. */ 701ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 702ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic 703ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownAMD64AMode* genGuestArrayOffset ( ISelEnv* env, IRRegArray* descr, 704ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRExpr* off, Int bias ) 705ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 706ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg tmp, roff; 707ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int elemSz = sizeofIRType(descr->elemTy); 708ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int nElems = descr->nElems; 709ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 710ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Throw out any cases not generated by an amd64 front end. In 711ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown theory there might be a day where we need to handle them -- if 712ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown we ever run non-amd64-guest on amd64 host. */ 713ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 714ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (nElems != 8 || (elemSz != 1 && elemSz != 8)) 715ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vpanic("genGuestArrayOffset(amd64 host)"); 716ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 717ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Compute off into a reg, %off. Then return: 718ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 719ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown movq %off, %tmp 720ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addq $bias, %tmp (if bias != 0) 721ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown andq %tmp, 7 722ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ... base(%rbp, %tmp, shift) ... 723ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */ 724ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tmp = newVRegI(env); 725ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown roff = iselIntExpr_R(env, off); 726ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, mk_iMOVsd_RR(roff, tmp)); 727ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (bias != 0) { 728ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Make sure the bias is sane, in the sense that there are 729ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown no significant bits above bit 30 in it. */ 730ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert(-10000 < bias && bias < 10000); 731ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, 732ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown AMD64Instr_Alu64R(Aalu_ADD, AMD64RMI_Imm(bias), tmp)); 733ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 734ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, 735ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown AMD64Instr_Alu64R(Aalu_AND, AMD64RMI_Imm(7), tmp)); 736ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert(elemSz == 1 || elemSz == 8); 737ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return 738ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown AMD64AMode_IRRS( descr->base, hregAMD64_RBP(), tmp, 739ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown elemSz==8 ? 3 : 0); 740ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 741ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 742ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 743ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Set the SSE unit's rounding mode to default (%mxcsr = 0x1F80) */ 744ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic 745ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid set_SSE_rounding_default ( ISelEnv* env ) 746ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 747ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* pushq $DEFAULT_MXCSR 748ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ldmxcsr 0(%rsp) 749ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addq $8, %rsp 750ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */ 751ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown AMD64AMode* zero_rsp = AMD64AMode_IR(0, hregAMD64_RSP()); 752ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_Push(AMD64RMI_Imm(DEFAULT_MXCSR))); 753ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_LdMXCSR(zero_rsp)); 754ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown add_to_rsp(env, 8); 755ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 756ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 757ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Mess with the FPU's rounding mode: set to the default rounding mode 758ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (DEFAULT_FPUCW). */ 759ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic 760ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid set_FPU_rounding_default ( ISelEnv* env ) 761ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 762ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* movq $DEFAULT_FPUCW, -8(%rsp) 763ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fldcw -8(%esp) 764ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */ 765ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown AMD64AMode* m8_rsp = AMD64AMode_IR(-8, hregAMD64_RSP()); 766ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_Alu64M( 767ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Aalu_MOV, AMD64RI_Imm(DEFAULT_FPUCW), m8_rsp)); 768ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_A87LdCW(m8_rsp)); 769ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 770ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 771ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 772ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Mess with the SSE unit's rounding mode: 'mode' is an I32-typed 773ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown expression denoting a value in the range 0 .. 3, indicating a round 774ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mode encoded as per type IRRoundingMode. Set the SSE machinery to 775ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown have the same rounding. 776ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/ 777ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic 778ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid set_SSE_rounding_mode ( ISelEnv* env, IRExpr* mode ) 779ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 780ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Note: this sequence only makes sense because DEFAULT_MXCSR has 781ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown both rounding bits == 0. If that wasn't the case, we couldn't 782ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown create a new rounding field simply by ORing the new value into 783ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown place. */ 784ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 785ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* movq $3, %reg 786ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown andq [[mode]], %reg -- shouldn't be needed; paranoia 787ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown shlq $13, %reg 788ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown orq $DEFAULT_MXCSR, %reg 789ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pushq %reg 790ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ldmxcsr 0(%esp) 791ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addq $8, %rsp 792ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */ 793ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg reg = newVRegI(env); 794ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown AMD64AMode* zero_rsp = AMD64AMode_IR(0, hregAMD64_RSP()); 795ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_Alu64R(Aalu_MOV, AMD64RMI_Imm(3), reg)); 796ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_Alu64R(Aalu_AND, 797ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown iselIntExpr_RMI(env, mode), reg)); 798ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_Sh64(Ash_SHL, 13, reg)); 799ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_Alu64R( 800ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Aalu_OR, AMD64RMI_Imm(DEFAULT_MXCSR), reg)); 801ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_Push(AMD64RMI_Reg(reg))); 802ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_LdMXCSR(zero_rsp)); 803ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown add_to_rsp(env, 8); 804ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 805ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 806ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 807ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Mess with the FPU's rounding mode: 'mode' is an I32-typed 808ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown expression denoting a value in the range 0 .. 3, indicating a round 809ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mode encoded as per type IRRoundingMode. Set the x87 FPU to have 810ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown the same rounding. 811ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/ 812ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic 813ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid set_FPU_rounding_mode ( ISelEnv* env, IRExpr* mode ) 814ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 815ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg rrm = iselIntExpr_R(env, mode); 816ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg rrm2 = newVRegI(env); 817ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown AMD64AMode* m8_rsp = AMD64AMode_IR(-8, hregAMD64_RSP()); 818ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 819ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* movq %rrm, %rrm2 820ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown andq $3, %rrm2 -- shouldn't be needed; paranoia 821ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown shlq $10, %rrm2 822ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown orq $DEFAULT_FPUCW, %rrm2 823ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown movq %rrm2, -8(%rsp) 824ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fldcw -8(%esp) 825ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */ 826ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, mk_iMOVsd_RR(rrm, rrm2)); 827ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_Alu64R(Aalu_AND, AMD64RMI_Imm(3), rrm2)); 828ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_Sh64(Ash_SHL, 10, rrm2)); 829ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_Alu64R(Aalu_OR, 830ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown AMD64RMI_Imm(DEFAULT_FPUCW), rrm2)); 831ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_Alu64M(Aalu_MOV, 832ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown AMD64RI_Reg(rrm2), m8_rsp)); 833ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_A87LdCW(m8_rsp)); 834ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 835ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 836ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 837ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Generate all-zeroes into a new vector register. 838ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/ 839ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic HReg generate_zeroes_V128 ( ISelEnv* env ) 840ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 841ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg dst = newVRegV(env); 842ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_SseReRg(Asse_XOR, dst, dst)); 843ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return dst; 844ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 845ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 846ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Generate all-ones into a new vector register. 847ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/ 848ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic HReg generate_ones_V128 ( ISelEnv* env ) 849ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 850ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg dst = newVRegV(env); 851ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_SseReRg(Asse_CMPEQ32, dst, dst)); 852ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return dst; 853ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 854ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 855ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 856ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Generate !src into a new vector register. Amazing that there isn't 857ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown a less crappy way to do this. 858ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/ 859ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic HReg do_sse_NotV128 ( ISelEnv* env, HReg src ) 860ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 861ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg dst = generate_ones_V128(env); 862ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_SseReRg(Asse_XOR, src, dst)); 863ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return dst; 864ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 865ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 866ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 867ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Expand the given byte into a 64-bit word, by cloning each bit 868ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 8 times. */ 869ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic ULong bitmask8_to_bytemask64 ( UShort w8 ) 870ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 871ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert(w8 == (w8 & 0xFF)); 872ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ULong w64 = 0; 873ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int i; 874ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (i = 0; i < 8; i++) { 875ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (w8 & (1<<i)) 876ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown w64 |= (0xFFULL << (8 * i)); 877ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 878ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return w64; 879ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 880ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 881ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 882ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------*/ 883ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- ISEL: Integer expressions (64/32/16/8 bit) ---*/ 884ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------*/ 885ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 886ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Select insns for an integer-typed expression, and add them to the 887ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown code list. Return a reg holding the result. This reg will be a 888ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown virtual register. THE RETURNED REG MUST NOT BE MODIFIED. If you 889ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown want to modify it, ask for a new vreg, copy it in there, and modify 890ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown the copy. The register allocator will do its best to map both 891ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vregs to the same real register, so the copies will often disappear 892ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown later in the game. 893ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 894ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown This should handle expressions of 64, 32, 16 and 8-bit type. All 895ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown results are returned in a 64-bit register. For 32-, 16- and 8-bit 896436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov expressions, the upper 32/48/56 bits are arbitrary, so you should 897ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mask or sign extend partial values if necessary. 898ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/ 899ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 900ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic HReg iselIntExpr_R ( ISelEnv* env, IRExpr* e ) 901ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 902ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg r = iselIntExpr_R_wrk(env, e); 903ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* sanity checks ... */ 904ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# if 0 905ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vex_printf("\niselIntExpr_R: "); ppIRExpr(e); vex_printf("\n"); 906ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 907ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert(hregClass(r) == HRcInt64); 908ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert(hregIsVirtual(r)); 909ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return r; 910ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 911ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 912ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* DO NOT CALL THIS DIRECTLY ! */ 913ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic HReg iselIntExpr_R_wrk ( ISelEnv* env, IRExpr* e ) 914ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 915ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Used for unary/binary SIMD64 ops. */ 916ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HWord fn = 0; 917ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bool second_is_UInt; 918ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 919ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown MatchInfo mi; 920ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DECLARE_PATTERN(p_1Uto8_64to1); 921ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DECLARE_PATTERN(p_LDle8_then_8Uto64); 922ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DECLARE_PATTERN(p_LDle16_then_16Uto64); 923ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 924ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRType ty = typeOfIRExpr(env->type_env,e); 925b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov switch (ty) { 926b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov case Ity_I64: case Ity_I32: case Ity_I16: case Ity_I8: break; 927b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov default: vassert(0); 928b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } 929ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 930ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (e->tag) { 931ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 932ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* --------- TEMP --------- */ 933ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iex_RdTmp: { 934ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return lookupIRTemp(env, e->Iex.RdTmp.tmp); 935ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 936ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 937ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* --------- LOAD --------- */ 938ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iex_Load: { 939ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg dst = newVRegI(env); 940ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown AMD64AMode* amode = iselIntExpr_AMode ( env, e->Iex.Load.addr ); 941ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 942ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* We can't handle big-endian loads, nor load-linked. */ 943ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->Iex.Load.end != Iend_LE) 944ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown goto irreducible; 945ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 946ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (ty == Ity_I64) { 947ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_Alu64R(Aalu_MOV, 948ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown AMD64RMI_Mem(amode), dst) ); 949ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return dst; 950ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 951ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (ty == Ity_I32) { 952ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_LoadEX(4,False,amode,dst)); 953ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return dst; 954ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 955ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (ty == Ity_I16) { 956ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_LoadEX(2,False,amode,dst)); 957ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return dst; 958ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 959ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (ty == Ity_I8) { 960ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_LoadEX(1,False,amode,dst)); 961ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return dst; 962ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 963ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 964ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 965ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 966ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* --------- BINARY OP --------- */ 967ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iex_Binop: { 968ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown AMD64AluOp aluOp; 969ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown AMD64ShiftOp shOp; 970ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 971ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Pattern: Sub64(0,x) */ 972ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* and: Sub32(0,x) */ 973ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if ((e->Iex.Binop.op == Iop_Sub64 && isZeroU64(e->Iex.Binop.arg1)) 974ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown || (e->Iex.Binop.op == Iop_Sub32 && isZeroU32(e->Iex.Binop.arg1))) { 975ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg dst = newVRegI(env); 976ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg reg = iselIntExpr_R(env, e->Iex.Binop.arg2); 977ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, mk_iMOVsd_RR(reg,dst)); 978ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_Unary64(Aun_NEG,dst)); 979ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return dst; 980ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 981ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 982ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Is it an addition or logical style op? */ 983ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (e->Iex.Binop.op) { 984ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Add8: case Iop_Add16: case Iop_Add32: case Iop_Add64: 985ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown aluOp = Aalu_ADD; break; 986ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Sub8: case Iop_Sub16: case Iop_Sub32: case Iop_Sub64: 987ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown aluOp = Aalu_SUB; break; 988ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_And8: case Iop_And16: case Iop_And32: case Iop_And64: 989ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown aluOp = Aalu_AND; break; 990ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Or8: case Iop_Or16: case Iop_Or32: case Iop_Or64: 991ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown aluOp = Aalu_OR; break; 992ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Xor8: case Iop_Xor16: case Iop_Xor32: case Iop_Xor64: 993ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown aluOp = Aalu_XOR; break; 994ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Mul16: case Iop_Mul32: case Iop_Mul64: 995ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown aluOp = Aalu_MUL; break; 996ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: 997ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown aluOp = Aalu_INVALID; break; 998ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 999ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* For commutative ops we assume any literal 1000ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown values are on the second operand. */ 1001ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (aluOp != Aalu_INVALID) { 1002ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg dst = newVRegI(env); 1003ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg reg = iselIntExpr_R(env, e->Iex.Binop.arg1); 1004ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown AMD64RMI* rmi = iselIntExpr_RMI(env, e->Iex.Binop.arg2); 1005ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, mk_iMOVsd_RR(reg,dst)); 1006ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_Alu64R(aluOp, rmi, dst)); 1007ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return dst; 1008ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1009ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1010ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Perhaps a shift op? */ 1011ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (e->Iex.Binop.op) { 1012ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Shl64: case Iop_Shl32: case Iop_Shl16: case Iop_Shl8: 1013ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown shOp = Ash_SHL; break; 1014ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Shr64: case Iop_Shr32: case Iop_Shr16: case Iop_Shr8: 1015ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown shOp = Ash_SHR; break; 1016ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Sar64: case Iop_Sar32: case Iop_Sar16: case Iop_Sar8: 1017ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown shOp = Ash_SAR; break; 1018ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: 1019ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown shOp = Ash_INVALID; break; 1020ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1021ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (shOp != Ash_INVALID) { 1022ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg dst = newVRegI(env); 1023ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1024ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* regL = the value to be shifted */ 1025ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg regL = iselIntExpr_R(env, e->Iex.Binop.arg1); 1026ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, mk_iMOVsd_RR(regL,dst)); 1027ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1028ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Do any necessary widening for 32/16/8 bit operands */ 1029ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (e->Iex.Binop.op) { 1030ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Shr64: case Iop_Shl64: case Iop_Sar64: 1031ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 1032ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Shl32: case Iop_Shl16: case Iop_Shl8: 1033ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 1034ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Shr8: 1035ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_Alu64R( 1036ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Aalu_AND, AMD64RMI_Imm(0xFF), dst)); 1037ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 1038ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Shr16: 1039ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_Alu64R( 1040ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Aalu_AND, AMD64RMI_Imm(0xFFFF), dst)); 1041ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 1042ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Shr32: 1043ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_MovxLQ(False, dst, dst)); 1044ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 1045ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Sar8: 1046ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_Sh64(Ash_SHL, 56, dst)); 1047ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_Sh64(Ash_SAR, 56, dst)); 1048ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 1049ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Sar16: 1050ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_Sh64(Ash_SHL, 48, dst)); 1051ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_Sh64(Ash_SAR, 48, dst)); 1052ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 1053ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Sar32: 1054ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_MovxLQ(True, dst, dst)); 1055ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 1056ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: 1057ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ppIROp(e->Iex.Binop.op); 1058ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert(0); 1059ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1060ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1061ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Now consider the shift amount. If it's a literal, we 1062ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown can do a much better job than the general case. */ 1063ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->Iex.Binop.arg2->tag == Iex_Const) { 1064ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* assert that the IR is well-typed */ 1065ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int nshift; 1066ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert(e->Iex.Binop.arg2->Iex.Const.con->tag == Ico_U8); 1067ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown nshift = e->Iex.Binop.arg2->Iex.Const.con->Ico.U8; 1068ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert(nshift >= 0); 1069ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (nshift > 0) 1070ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Can't allow nshift==0 since that means %cl */ 1071ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_Sh64(shOp, nshift, dst)); 1072ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 1073ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* General case; we have to force the amount into %cl. */ 1074ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg regR = iselIntExpr_R(env, e->Iex.Binop.arg2); 1075ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, mk_iMOVsd_RR(regR,hregAMD64_RCX())); 1076ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_Sh64(shOp, 0/* %cl */, dst)); 1077ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1078ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return dst; 1079ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1080ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1081ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Deal with 64-bit SIMD binary ops */ 1082ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown second_is_UInt = False; 1083ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (e->Iex.Binop.op) { 1084ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Add8x8: 1085ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fn = (HWord)h_generic_calc_Add8x8; break; 1086ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Add16x4: 1087ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fn = (HWord)h_generic_calc_Add16x4; break; 1088ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Add32x2: 1089ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fn = (HWord)h_generic_calc_Add32x2; break; 1090ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1091ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Avg8Ux8: 1092ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fn = (HWord)h_generic_calc_Avg8Ux8; break; 1093ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Avg16Ux4: 1094ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fn = (HWord)h_generic_calc_Avg16Ux4; break; 1095ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1096ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CmpEQ8x8: 1097ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fn = (HWord)h_generic_calc_CmpEQ8x8; break; 1098ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CmpEQ16x4: 1099ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fn = (HWord)h_generic_calc_CmpEQ16x4; break; 1100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CmpEQ32x2: 1101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fn = (HWord)h_generic_calc_CmpEQ32x2; break; 1102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CmpGT8Sx8: 1104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fn = (HWord)h_generic_calc_CmpGT8Sx8; break; 1105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CmpGT16Sx4: 1106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fn = (HWord)h_generic_calc_CmpGT16Sx4; break; 1107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CmpGT32Sx2: 1108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fn = (HWord)h_generic_calc_CmpGT32Sx2; break; 1109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_InterleaveHI8x8: 1111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fn = (HWord)h_generic_calc_InterleaveHI8x8; break; 1112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_InterleaveLO8x8: 1113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fn = (HWord)h_generic_calc_InterleaveLO8x8; break; 1114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_InterleaveHI16x4: 1115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fn = (HWord)h_generic_calc_InterleaveHI16x4; break; 1116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_InterleaveLO16x4: 1117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fn = (HWord)h_generic_calc_InterleaveLO16x4; break; 1118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_InterleaveHI32x2: 1119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fn = (HWord)h_generic_calc_InterleaveHI32x2; break; 1120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_InterleaveLO32x2: 1121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fn = (HWord)h_generic_calc_InterleaveLO32x2; break; 1122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CatOddLanes16x4: 1123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fn = (HWord)h_generic_calc_CatOddLanes16x4; break; 1124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CatEvenLanes16x4: 1125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fn = (HWord)h_generic_calc_CatEvenLanes16x4; break; 1126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Perm8x8: 1127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fn = (HWord)h_generic_calc_Perm8x8; break; 1128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Max8Ux8: 1130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fn = (HWord)h_generic_calc_Max8Ux8; break; 1131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Max16Sx4: 1132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fn = (HWord)h_generic_calc_Max16Sx4; break; 1133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Min8Ux8: 1134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fn = (HWord)h_generic_calc_Min8Ux8; break; 1135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Min16Sx4: 1136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fn = (HWord)h_generic_calc_Min16Sx4; break; 1137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Mul16x4: 1139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fn = (HWord)h_generic_calc_Mul16x4; break; 1140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Mul32x2: 1141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fn = (HWord)h_generic_calc_Mul32x2; break; 1142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_MulHi16Sx4: 1143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fn = (HWord)h_generic_calc_MulHi16Sx4; break; 1144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_MulHi16Ux4: 1145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fn = (HWord)h_generic_calc_MulHi16Ux4; break; 1146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QAdd8Sx8: 1148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fn = (HWord)h_generic_calc_QAdd8Sx8; break; 1149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QAdd16Sx4: 1150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fn = (HWord)h_generic_calc_QAdd16Sx4; break; 1151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QAdd8Ux8: 1152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fn = (HWord)h_generic_calc_QAdd8Ux8; break; 1153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QAdd16Ux4: 1154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fn = (HWord)h_generic_calc_QAdd16Ux4; break; 1155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1156b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov case Iop_QNarrowBin32Sto16Sx4: 1157b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov fn = (HWord)h_generic_calc_QNarrowBin32Sto16Sx4; break; 1158b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov case Iop_QNarrowBin16Sto8Sx8: 1159b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov fn = (HWord)h_generic_calc_QNarrowBin16Sto8Sx8; break; 1160b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov case Iop_QNarrowBin16Sto8Ux8: 1161b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov fn = (HWord)h_generic_calc_QNarrowBin16Sto8Ux8; break; 1162b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov case Iop_NarrowBin16to8x8: 1163b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov fn = (HWord)h_generic_calc_NarrowBin16to8x8; break; 1164b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov case Iop_NarrowBin32to16x4: 1165b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov fn = (HWord)h_generic_calc_NarrowBin32to16x4; break; 1166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QSub8Sx8: 1168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fn = (HWord)h_generic_calc_QSub8Sx8; break; 1169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QSub16Sx4: 1170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fn = (HWord)h_generic_calc_QSub16Sx4; break; 1171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QSub8Ux8: 1172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fn = (HWord)h_generic_calc_QSub8Ux8; break; 1173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QSub16Ux4: 1174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fn = (HWord)h_generic_calc_QSub16Ux4; break; 1175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Sub8x8: 1177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fn = (HWord)h_generic_calc_Sub8x8; break; 1178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Sub16x4: 1179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fn = (HWord)h_generic_calc_Sub16x4; break; 1180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Sub32x2: 1181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fn = (HWord)h_generic_calc_Sub32x2; break; 1182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_ShlN32x2: 1184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fn = (HWord)h_generic_calc_ShlN32x2; 1185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown second_is_UInt = True; 1186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 1187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_ShlN16x4: 1188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fn = (HWord)h_generic_calc_ShlN16x4; 1189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown second_is_UInt = True; 1190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 1191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_ShlN8x8: 1192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fn = (HWord)h_generic_calc_ShlN8x8; 1193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown second_is_UInt = True; 1194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 1195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_ShrN32x2: 1196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fn = (HWord)h_generic_calc_ShrN32x2; 1197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown second_is_UInt = True; 1198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 1199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_ShrN16x4: 1200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fn = (HWord)h_generic_calc_ShrN16x4; 1201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown second_is_UInt = True; 1202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 1203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_SarN32x2: 1204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fn = (HWord)h_generic_calc_SarN32x2; 1205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown second_is_UInt = True; 1206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 1207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_SarN16x4: 1208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fn = (HWord)h_generic_calc_SarN16x4; 1209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown second_is_UInt = True; 1210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 1211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_SarN8x8: 1212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fn = (HWord)h_generic_calc_SarN8x8; 1213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown second_is_UInt = True; 1214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 1215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: 1217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fn = (HWord)0; break; 1218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (fn != (HWord)0) { 1220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Note: the following assumes all helpers are of signature 1221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ULong fn ( ULong, ULong ), and they are 1222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown not marked as regparm functions. 1223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */ 1224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg dst = newVRegI(env); 1225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselIntExpr_R(env, e->Iex.Binop.arg1); 1226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselIntExpr_R(env, e->Iex.Binop.arg2); 1227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (second_is_UInt) 1228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_MovxLQ(False, argR, argR)); 1229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, mk_iMOVsd_RR(argL, hregAMD64_RDI()) ); 1230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, mk_iMOVsd_RR(argR, hregAMD64_RSI()) ); 1231436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov addInstr(env, AMD64Instr_Call( Acc_ALWAYS, (ULong)fn, 2, 1232436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov mk_RetLoc_simple(RLPri_Int) )); 1233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, mk_iMOVsd_RR(hregAMD64_RAX(), dst)); 1234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return dst; 1235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Handle misc other ops. */ 1238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->Iex.Binop.op == Iop_Max32U) { 1240b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov HReg src1 = iselIntExpr_R(env, e->Iex.Binop.arg1); 1241b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov HReg dst = newVRegI(env); 1242b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov HReg src2 = iselIntExpr_R(env, e->Iex.Binop.arg2); 1243b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov addInstr(env, mk_iMOVsd_RR(src1, dst)); 1244b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov addInstr(env, AMD64Instr_Alu32R(Aalu_CMP, AMD64RMI_Reg(src2), dst)); 1245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_CMov64(Acc_B, AMD64RM_Reg(src2), dst)); 1246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return dst; 1247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->Iex.Binop.op == Iop_DivModS64to32 1250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown || e->Iex.Binop.op == Iop_DivModU64to32) { 1251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* 64 x 32 -> (32(rem),32(div)) division */ 1252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Get the 64-bit operand into edx:eax, and the other into 1253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown any old R/M. */ 1254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg rax = hregAMD64_RAX(); 1255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg rdx = hregAMD64_RDX(); 1256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg dst = newVRegI(env); 1257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bool syned = toBool(e->Iex.Binop.op == Iop_DivModS64to32); 1258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown AMD64RM* rmRight = iselIntExpr_RM(env, e->Iex.Binop.arg2); 1259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Compute the left operand into a reg, and then 1260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown put the top half in edx and the bottom in eax. */ 1261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg left64 = iselIntExpr_R(env, e->Iex.Binop.arg1); 1262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, mk_iMOVsd_RR(left64, rdx)); 1263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, mk_iMOVsd_RR(left64, rax)); 1264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_Sh64(Ash_SHR, 32, rdx)); 1265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_Div(syned, 4, rmRight)); 1266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_MovxLQ(False, rdx, rdx)); 1267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_MovxLQ(False, rax, rax)); 1268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_Sh64(Ash_SHL, 32, rdx)); 1269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, mk_iMOVsd_RR(rax, dst)); 1270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_Alu64R(Aalu_OR, AMD64RMI_Reg(rdx), dst)); 1271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return dst; 1272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->Iex.Binop.op == Iop_32HLto64) { 1275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg hi32 = newVRegI(env); 1276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg lo32 = newVRegI(env); 1277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg hi32s = iselIntExpr_R(env, e->Iex.Binop.arg1); 1278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg lo32s = iselIntExpr_R(env, e->Iex.Binop.arg2); 1279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, mk_iMOVsd_RR(hi32s, hi32)); 1280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, mk_iMOVsd_RR(lo32s, lo32)); 1281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_Sh64(Ash_SHL, 32, hi32)); 1282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_MovxLQ(False, lo32, lo32)); 1283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_Alu64R( 1284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Aalu_OR, AMD64RMI_Reg(lo32), hi32)); 1285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return hi32; 1286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->Iex.Binop.op == Iop_16HLto32) { 1289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg hi16 = newVRegI(env); 1290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg lo16 = newVRegI(env); 1291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg hi16s = iselIntExpr_R(env, e->Iex.Binop.arg1); 1292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg lo16s = iselIntExpr_R(env, e->Iex.Binop.arg2); 1293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, mk_iMOVsd_RR(hi16s, hi16)); 1294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, mk_iMOVsd_RR(lo16s, lo16)); 1295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_Sh64(Ash_SHL, 16, hi16)); 1296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_Alu64R( 1297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Aalu_AND, AMD64RMI_Imm(0xFFFF), lo16)); 1298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_Alu64R( 1299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Aalu_OR, AMD64RMI_Reg(lo16), hi16)); 1300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return hi16; 1301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->Iex.Binop.op == Iop_8HLto16) { 1304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg hi8 = newVRegI(env); 1305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg lo8 = newVRegI(env); 1306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg hi8s = iselIntExpr_R(env, e->Iex.Binop.arg1); 1307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg lo8s = iselIntExpr_R(env, e->Iex.Binop.arg2); 1308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, mk_iMOVsd_RR(hi8s, hi8)); 1309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, mk_iMOVsd_RR(lo8s, lo8)); 1310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_Sh64(Ash_SHL, 8, hi8)); 1311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_Alu64R( 1312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Aalu_AND, AMD64RMI_Imm(0xFF), lo8)); 1313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_Alu64R( 1314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Aalu_OR, AMD64RMI_Reg(lo8), hi8)); 1315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return hi8; 1316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->Iex.Binop.op == Iop_MullS32 1319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown || e->Iex.Binop.op == Iop_MullS16 1320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown || e->Iex.Binop.op == Iop_MullS8 1321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown || e->Iex.Binop.op == Iop_MullU32 1322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown || e->Iex.Binop.op == Iop_MullU16 1323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown || e->Iex.Binop.op == Iop_MullU8) { 1324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg a32 = newVRegI(env); 1325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg b32 = newVRegI(env); 1326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg a32s = iselIntExpr_R(env, e->Iex.Binop.arg1); 1327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg b32s = iselIntExpr_R(env, e->Iex.Binop.arg2); 1328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int shift = 0; 1329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown AMD64ShiftOp shr_op = Ash_SHR; 1330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (e->Iex.Binop.op) { 1331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_MullS32: shr_op = Ash_SAR; shift = 32; break; 1332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_MullS16: shr_op = Ash_SAR; shift = 48; break; 1333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_MullS8: shr_op = Ash_SAR; shift = 56; break; 1334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_MullU32: shr_op = Ash_SHR; shift = 32; break; 1335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_MullU16: shr_op = Ash_SHR; shift = 48; break; 1336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_MullU8: shr_op = Ash_SHR; shift = 56; break; 1337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: vassert(0); 1338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, mk_iMOVsd_RR(a32s, a32)); 1341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, mk_iMOVsd_RR(b32s, b32)); 1342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_Sh64(Ash_SHL, shift, a32)); 1343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_Sh64(Ash_SHL, shift, b32)); 1344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_Sh64(shr_op, shift, a32)); 1345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_Sh64(shr_op, shift, b32)); 1346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_Alu64R(Aalu_MUL, AMD64RMI_Reg(a32), b32)); 1347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return b32; 1348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->Iex.Binop.op == Iop_CmpF64) { 1351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg fL = iselDblExpr(env, e->Iex.Binop.arg1); 1352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg fR = iselDblExpr(env, e->Iex.Binop.arg2); 1353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg dst = newVRegI(env); 1354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_SseUComIS(8,fL,fR,dst)); 1355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Mask out irrelevant parts of the result so as to conform 1356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown to the CmpF64 definition. */ 1357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_Alu64R(Aalu_AND, AMD64RMI_Imm(0x45), dst)); 1358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return dst; 1359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->Iex.Binop.op == Iop_F64toI32S 1362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown || e->Iex.Binop.op == Iop_F64toI64S) { 1363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int szD = e->Iex.Binop.op==Iop_F64toI32S ? 4 : 8; 1364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg rf = iselDblExpr(env, e->Iex.Binop.arg2); 1365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg dst = newVRegI(env); 1366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown set_SSE_rounding_mode( env, e->Iex.Binop.arg1 ); 1367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_SseSF2SI( 8, szD, rf, dst )); 1368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown set_SSE_rounding_default(env); 1369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return dst; 1370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 1373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* --------- UNARY OP --------- */ 1376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iex_Unop: { 1377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* 1Uto8(64to1(expr64)) */ 1379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown { 1380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEFINE_PATTERN( p_1Uto8_64to1, 1381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown unop(Iop_1Uto8, unop(Iop_64to1, bind(0))) ); 1382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (matchIRExpr(&mi,p_1Uto8_64to1,e)) { 1383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRExpr* expr64 = mi.bindee[0]; 1384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg dst = newVRegI(env); 1385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg src = iselIntExpr_R(env, expr64); 1386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, mk_iMOVsd_RR(src,dst) ); 1387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_Alu64R(Aalu_AND, 1388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown AMD64RMI_Imm(1), dst)); 1389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return dst; 1390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* 8Uto64(LDle(expr64)) */ 1394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown { 1395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEFINE_PATTERN(p_LDle8_then_8Uto64, 1396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown unop(Iop_8Uto64, 1397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRExpr_Load(Iend_LE,Ity_I8,bind(0))) ); 1398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (matchIRExpr(&mi,p_LDle8_then_8Uto64,e)) { 1399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg dst = newVRegI(env); 1400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown AMD64AMode* amode = iselIntExpr_AMode ( env, mi.bindee[0] ); 1401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_LoadEX(1,False,amode,dst)); 1402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return dst; 1403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* 16Uto64(LDle(expr64)) */ 1407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown { 1408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEFINE_PATTERN(p_LDle16_then_16Uto64, 1409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown unop(Iop_16Uto64, 1410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRExpr_Load(Iend_LE,Ity_I16,bind(0))) ); 1411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (matchIRExpr(&mi,p_LDle16_then_16Uto64,e)) { 1412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg dst = newVRegI(env); 1413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown AMD64AMode* amode = iselIntExpr_AMode ( env, mi.bindee[0] ); 1414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_LoadEX(2,False,amode,dst)); 1415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return dst; 1416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1419b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov /* 32Uto64( Add32/Sub32/And32/Or32/Xor32(expr32, expr32) ) 1420b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov Use 32 bit arithmetic and let the default zero-extend rule 1421b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov do the 32Uto64 for free. */ 1422b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (e->Iex.Unop.op == Iop_32Uto64 && e->Iex.Unop.arg->tag == Iex_Binop) { 1423b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov IROp opi = e->Iex.Unop.arg->Iex.Binop.op; /* inner op */ 1424b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov IRExpr* argL = e->Iex.Unop.arg->Iex.Binop.arg1; 1425b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov IRExpr* argR = e->Iex.Unop.arg->Iex.Binop.arg2; 1426b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov AMD64AluOp aluOp = Aalu_INVALID; 1427b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov switch (opi) { 1428b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov case Iop_Add32: aluOp = Aalu_ADD; break; 1429b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov case Iop_Sub32: aluOp = Aalu_SUB; break; 1430b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov case Iop_And32: aluOp = Aalu_AND; break; 1431b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov case Iop_Or32: aluOp = Aalu_OR; break; 1432b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov case Iop_Xor32: aluOp = Aalu_XOR; break; 1433b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov default: break; 1434b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } 1435b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (aluOp != Aalu_INVALID) { 1436b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov /* For commutative ops we assume any literal values are on 1437b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov the second operand. */ 1438b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov HReg dst = newVRegI(env); 1439b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov HReg reg = iselIntExpr_R(env, argL); 1440b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov AMD64RMI* rmi = iselIntExpr_RMI(env, argR); 1441b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov addInstr(env, mk_iMOVsd_RR(reg,dst)); 1442b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov addInstr(env, AMD64Instr_Alu32R(aluOp, rmi, dst)); 1443b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov return dst; 1444b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } 1445b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov /* just fall through to normal handling for Iop_32Uto64 */ 1446b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } 1447b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 1448b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov /* Fallback cases */ 1449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (e->Iex.Unop.op) { 1450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_32Uto64: 1451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_32Sto64: { 1452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg dst = newVRegI(env); 1453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg src = iselIntExpr_R(env, e->Iex.Unop.arg); 1454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_MovxLQ(e->Iex.Unop.op == Iop_32Sto64, 1455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown src, dst) ); 1456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return dst; 1457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_128HIto64: { 1459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg rHi, rLo; 1460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown iselInt128Expr(&rHi,&rLo, env, e->Iex.Unop.arg); 1461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return rHi; /* and abandon rLo */ 1462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_128to64: { 1464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg rHi, rLo; 1465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown iselInt128Expr(&rHi,&rLo, env, e->Iex.Unop.arg); 1466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return rLo; /* and abandon rHi */ 1467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_8Uto16: 1469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_8Uto32: 1470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_8Uto64: 1471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_16Uto64: 1472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_16Uto32: { 1473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg dst = newVRegI(env); 1474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg src = iselIntExpr_R(env, e->Iex.Unop.arg); 1475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bool srcIs16 = toBool( e->Iex.Unop.op==Iop_16Uto32 1476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown || e->Iex.Unop.op==Iop_16Uto64 ); 1477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt mask = srcIs16 ? 0xFFFF : 0xFF; 1478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, mk_iMOVsd_RR(src,dst) ); 1479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_Alu64R(Aalu_AND, 1480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown AMD64RMI_Imm(mask), dst)); 1481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return dst; 1482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_8Sto16: 1484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_8Sto64: 1485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_8Sto32: 1486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_16Sto32: 1487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_16Sto64: { 1488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg dst = newVRegI(env); 1489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg src = iselIntExpr_R(env, e->Iex.Unop.arg); 1490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bool srcIs16 = toBool( e->Iex.Unop.op==Iop_16Sto32 1491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown || e->Iex.Unop.op==Iop_16Sto64 ); 1492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt amt = srcIs16 ? 48 : 56; 1493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, mk_iMOVsd_RR(src,dst) ); 1494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_Sh64(Ash_SHL, amt, dst)); 1495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_Sh64(Ash_SAR, amt, dst)); 1496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return dst; 1497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Not8: 1499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Not16: 1500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Not32: 1501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Not64: { 1502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg dst = newVRegI(env); 1503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg src = iselIntExpr_R(env, e->Iex.Unop.arg); 1504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, mk_iMOVsd_RR(src,dst) ); 1505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_Unary64(Aun_NOT,dst)); 1506ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return dst; 1507ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1508ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_16HIto8: 1509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_32HIto16: 1510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_64HIto32: { 1511ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg dst = newVRegI(env); 1512ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg src = iselIntExpr_R(env, e->Iex.Unop.arg); 1513ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int shift = 0; 1514ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (e->Iex.Unop.op) { 1515ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_16HIto8: shift = 8; break; 1516ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_32HIto16: shift = 16; break; 1517ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_64HIto32: shift = 32; break; 1518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: vassert(0); 1519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, mk_iMOVsd_RR(src,dst) ); 1521ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_Sh64(Ash_SHR, shift, dst)); 1522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return dst; 1523ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1524ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_1Uto64: 1525ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_1Uto32: 1526ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_1Uto8: { 1527ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg dst = newVRegI(env); 1528ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown AMD64CondCode cond = iselCondCode(env, e->Iex.Unop.arg); 1529ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_Set64(cond,dst)); 1530ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return dst; 1531ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1532ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_1Sto8: 1533ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_1Sto16: 1534ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_1Sto32: 1535ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_1Sto64: { 1536ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* could do better than this, but for now ... */ 1537ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg dst = newVRegI(env); 1538ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown AMD64CondCode cond = iselCondCode(env, e->Iex.Unop.arg); 1539ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_Set64(cond,dst)); 1540ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_Sh64(Ash_SHL, 63, dst)); 1541ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_Sh64(Ash_SAR, 63, dst)); 1542ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return dst; 1543ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1544ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Ctz64: { 1545ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Count trailing zeroes, implemented by amd64 'bsfq' */ 1546ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg dst = newVRegI(env); 1547ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg src = iselIntExpr_R(env, e->Iex.Unop.arg); 1548ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_Bsfr64(True,src,dst)); 1549ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return dst; 1550ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1551ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Clz64: { 1552ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Count leading zeroes. Do 'bsrq' to establish the index 1553ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown of the highest set bit, and subtract that value from 1554ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 63. */ 1555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg tmp = newVRegI(env); 1556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg dst = newVRegI(env); 1557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg src = iselIntExpr_R(env, e->Iex.Unop.arg); 1558ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_Bsfr64(False,src,tmp)); 1559ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_Alu64R(Aalu_MOV, 1560ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown AMD64RMI_Imm(63), dst)); 1561ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_Alu64R(Aalu_SUB, 1562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown AMD64RMI_Reg(tmp), dst)); 1563ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return dst; 1564ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1565ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1566ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CmpwNEZ64: { 1567ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg dst = newVRegI(env); 1568ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg src = iselIntExpr_R(env, e->Iex.Unop.arg); 1569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, mk_iMOVsd_RR(src,dst)); 1570ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_Unary64(Aun_NEG,dst)); 1571ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_Alu64R(Aalu_OR, 1572ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown AMD64RMI_Reg(src), dst)); 1573ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_Sh64(Ash_SAR, 63, dst)); 1574ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return dst; 1575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CmpwNEZ32: { 1578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg src = newVRegI(env); 1579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg dst = newVRegI(env); 1580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg pre = iselIntExpr_R(env, e->Iex.Unop.arg); 1581ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, mk_iMOVsd_RR(pre,src)); 1582ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_MovxLQ(False, src, src)); 1583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, mk_iMOVsd_RR(src,dst)); 1584ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_Unary64(Aun_NEG,dst)); 1585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_Alu64R(Aalu_OR, 1586ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown AMD64RMI_Reg(src), dst)); 1587ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_Sh64(Ash_SAR, 63, dst)); 1588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return dst; 1589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Left8: 1592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Left16: 1593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Left32: 1594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Left64: { 1595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg dst = newVRegI(env); 1596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg src = iselIntExpr_R(env, e->Iex.Unop.arg); 1597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, mk_iMOVsd_RR(src, dst)); 1598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_Unary64(Aun_NEG, dst)); 1599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_Alu64R(Aalu_OR, AMD64RMI_Reg(src), dst)); 1600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return dst; 1601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1602ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_V128to32: { 1604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg dst = newVRegI(env); 1605ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg vec = iselVecExpr(env, e->Iex.Unop.arg); 1606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown AMD64AMode* rsp_m16 = AMD64AMode_IR(-16, hregAMD64_RSP()); 1607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_SseLdSt(False/*store*/, 16, vec, rsp_m16)); 1608ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_LoadEX(4, False/*z-widen*/, rsp_m16, dst)); 1609ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return dst; 1610ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1612ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* V128{HI}to64 */ 1613ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_V128HIto64: 1614ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_V128to64: { 1615ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg dst = newVRegI(env); 1616663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng Int off = e->Iex.Unop.op==Iop_V128HIto64 ? -8 : -16; 1617663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng HReg rsp = hregAMD64_RSP(); 1618ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg vec = iselVecExpr(env, e->Iex.Unop.arg); 1619663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng AMD64AMode* m16_rsp = AMD64AMode_IR(-16, rsp); 1620663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng AMD64AMode* off_rsp = AMD64AMode_IR(off, rsp); 1621663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng addInstr(env, AMD64Instr_SseLdSt(False/*store*/, 1622663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 16, vec, m16_rsp)); 1623ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_Alu64R( Aalu_MOV, 1624663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng AMD64RMI_Mem(off_rsp), dst )); 1625663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng return dst; 1626663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng } 1627663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 1628663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng case Iop_V256to64_0: case Iop_V256to64_1: 1629663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng case Iop_V256to64_2: case Iop_V256to64_3: { 1630663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng HReg vHi, vLo, vec; 1631663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng iselDVecExpr(&vHi, &vLo, env, e->Iex.Unop.arg); 1632663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng /* Do the first part of the selection by deciding which of 1633663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng the 128 bit registers do look at, and second part using 1634663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng the same scheme as for V128{HI}to64 above. */ 1635663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng Int off = 0; 1636663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng switch (e->Iex.Unop.op) { 1637663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng case Iop_V256to64_0: vec = vLo; off = -16; break; 1638663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng case Iop_V256to64_1: vec = vLo; off = -8; break; 1639663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng case Iop_V256to64_2: vec = vHi; off = -16; break; 1640663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng case Iop_V256to64_3: vec = vHi; off = -8; break; 1641663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng default: vassert(0); 1642663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng } 1643663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng HReg dst = newVRegI(env); 1644663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng HReg rsp = hregAMD64_RSP(); 1645663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng AMD64AMode* m16_rsp = AMD64AMode_IR(-16, rsp); 1646663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng AMD64AMode* off_rsp = AMD64AMode_IR(off, rsp); 1647663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng addInstr(env, AMD64Instr_SseLdSt(False/*store*/, 1648663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 16, vec, m16_rsp)); 1649663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng addInstr(env, AMD64Instr_Alu64R( Aalu_MOV, 1650663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng AMD64RMI_Mem(off_rsp), dst )); 1651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return dst; 1652ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1653ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1654ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* ReinterpF64asI64(e) */ 1655ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Given an IEEE754 double, produce an I64 with the same bit 1656ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pattern. */ 1657ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_ReinterpF64asI64: { 1658ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown AMD64AMode* m8_rsp = AMD64AMode_IR(-8, hregAMD64_RSP()); 1659ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg dst = newVRegI(env); 1660ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg src = iselDblExpr(env, e->Iex.Unop.arg); 1661ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* paranoia */ 1662ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown set_SSE_rounding_default(env); 1663ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_SseLdSt(False/*store*/, 8, src, m8_rsp)); 1664ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_Alu64R( 1665ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Aalu_MOV, AMD64RMI_Mem(m8_rsp), dst)); 1666ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return dst; 1667ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1668ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1669ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* ReinterpF32asI32(e) */ 1670ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Given an IEEE754 single, produce an I64 with the same bit 1671ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pattern in the lower half. */ 1672ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_ReinterpF32asI32: { 1673ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown AMD64AMode* m8_rsp = AMD64AMode_IR(-8, hregAMD64_RSP()); 1674ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg dst = newVRegI(env); 1675ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg src = iselFltExpr(env, e->Iex.Unop.arg); 1676ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* paranoia */ 1677ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown set_SSE_rounding_default(env); 1678ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_SseLdSt(False/*store*/, 4, src, m8_rsp)); 1679ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_LoadEX(4, False/*unsigned*/, m8_rsp, dst )); 1680ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return dst; 1681ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1682ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1683ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_16to8: 1684ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_32to8: 1685ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_64to8: 1686ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_32to16: 1687ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_64to16: 1688ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_64to32: 1689ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* These are no-ops. */ 1690ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return iselIntExpr_R(env, e->Iex.Unop.arg); 1691ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1692436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case Iop_GetMSBs8x8: { 1693436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /* Note: the following assumes the helper is of 1694436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov signature 1695436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov UInt fn ( ULong ), and is not a regparm fn. 1696436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov */ 1697436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov HReg dst = newVRegI(env); 1698436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov HReg arg = iselIntExpr_R(env, e->Iex.Unop.arg); 1699436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov fn = (HWord)h_generic_calc_GetMSBs8x8; 1700436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov addInstr(env, mk_iMOVsd_RR(arg, hregAMD64_RDI()) ); 1701436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov addInstr(env, AMD64Instr_Call( Acc_ALWAYS, (ULong)fn, 1702436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 1, mk_RetLoc_simple(RLPri_Int) )); 1703436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /* MovxLQ is not exactly the right thing here. We just 1704436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov need to get the bottom 8 bits of RAX into dst, and zero 1705436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov out everything else. Assuming that the helper returns 1706436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov a UInt with the top 24 bits zeroed out, it'll do, 1707436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov though. */ 1708436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov addInstr(env, AMD64Instr_MovxLQ(False, hregAMD64_RAX(), dst)); 1709436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov return dst; 1710436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } 1711436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 1712436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case Iop_GetMSBs8x16: { 1713436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /* Note: the following assumes the helper is of signature 1714436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov UInt fn ( ULong w64hi, ULong w64Lo ), 1715436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov and is not a regparm fn. */ 1716436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov HReg dst = newVRegI(env); 1717436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov HReg vec = iselVecExpr(env, e->Iex.Unop.arg); 1718436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov HReg rsp = hregAMD64_RSP(); 1719436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov fn = (HWord)h_generic_calc_GetMSBs8x16; 1720436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov AMD64AMode* m8_rsp = AMD64AMode_IR( -8, rsp); 1721436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov AMD64AMode* m16_rsp = AMD64AMode_IR(-16, rsp); 1722436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov addInstr(env, AMD64Instr_SseLdSt(False/*store*/, 1723436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 16, vec, m16_rsp)); 1724436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /* hi 64 bits into RDI -- the first arg */ 1725436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov addInstr(env, AMD64Instr_Alu64R( Aalu_MOV, 1726436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov AMD64RMI_Mem(m8_rsp), 1727436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov hregAMD64_RDI() )); /* 1st arg */ 1728436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /* lo 64 bits into RSI -- the 2nd arg */ 1729436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov addInstr(env, AMD64Instr_Alu64R( Aalu_MOV, 1730436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov AMD64RMI_Mem(m16_rsp), 1731436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov hregAMD64_RSI() )); /* 2nd arg */ 1732436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov addInstr(env, AMD64Instr_Call( Acc_ALWAYS, (ULong)fn, 1733436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 2, mk_RetLoc_simple(RLPri_Int) )); 1734436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /* MovxLQ is not exactly the right thing here. We just 1735436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov need to get the bottom 16 bits of RAX into dst, and zero 1736436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov out everything else. Assuming that the helper returns 1737436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov a UInt with the top 16 bits zeroed out, it'll do, 1738436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov though. */ 1739436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov addInstr(env, AMD64Instr_MovxLQ(False, hregAMD64_RAX(), dst)); 1740436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov return dst; 1741436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } 1742436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 1743ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: 1744ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 1745ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1746ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1747ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Deal with unary 64-bit SIMD ops. */ 1748ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (e->Iex.Unop.op) { 1749ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CmpNEZ32x2: 1750ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fn = (HWord)h_generic_calc_CmpNEZ32x2; break; 1751ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CmpNEZ16x4: 1752ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fn = (HWord)h_generic_calc_CmpNEZ16x4; break; 1753ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CmpNEZ8x8: 1754ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fn = (HWord)h_generic_calc_CmpNEZ8x8; break; 1755ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: 1756ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fn = (HWord)0; break; 1757ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1758ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (fn != (HWord)0) { 1759ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Note: the following assumes all helpers are of 1760ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown signature 1761ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ULong fn ( ULong ), and they are 1762ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown not marked as regparm functions. 1763ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */ 1764ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg dst = newVRegI(env); 1765ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg arg = iselIntExpr_R(env, e->Iex.Unop.arg); 1766ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, mk_iMOVsd_RR(arg, hregAMD64_RDI()) ); 1767436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov addInstr(env, AMD64Instr_Call( Acc_ALWAYS, (ULong)fn, 1, 1768436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov mk_RetLoc_simple(RLPri_Int) )); 1769ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, mk_iMOVsd_RR(hregAMD64_RAX(), dst)); 1770ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return dst; 1771ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1772ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1773ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 1774ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1775ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1776ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* --------- GET --------- */ 1777ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iex_Get: { 1778ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (ty == Ity_I64) { 1779ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg dst = newVRegI(env); 1780ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_Alu64R( 1781ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Aalu_MOV, 1782ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown AMD64RMI_Mem( 1783ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown AMD64AMode_IR(e->Iex.Get.offset, 1784ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown hregAMD64_RBP())), 1785ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown dst)); 1786ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return dst; 1787ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1788ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (ty == Ity_I8 || ty == Ity_I16 || ty == Ity_I32) { 1789ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg dst = newVRegI(env); 1790ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_LoadEX( 1791ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown toUChar(ty==Ity_I8 ? 1 : (ty==Ity_I16 ? 2 : 4)), 1792ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown False, 1793ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown AMD64AMode_IR(e->Iex.Get.offset,hregAMD64_RBP()), 1794ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown dst)); 1795ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return dst; 1796ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1797ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 1798ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1799ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1800ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iex_GetI: { 1801ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown AMD64AMode* am 1802ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown = genGuestArrayOffset( 1803ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown env, e->Iex.GetI.descr, 1804ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown e->Iex.GetI.ix, e->Iex.GetI.bias ); 1805ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg dst = newVRegI(env); 1806ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (ty == Ity_I8) { 1807ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_LoadEX( 1, False, am, dst )); 1808ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return dst; 1809ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1810ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (ty == Ity_I64) { 1811ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_Alu64R( Aalu_MOV, AMD64RMI_Mem(am), dst )); 1812ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return dst; 1813ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1814ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 1815ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1816ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1817ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* --------- CCALL --------- */ 1818ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iex_CCall: { 1819ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg dst = newVRegI(env); 1820ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert(ty == e->Iex.CCall.retty); 1821ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1822436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /* be very restrictive for now. Only 64-bit ints allowed for 1823436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov args, and 64 or 32 bits for return type. */ 1824ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->Iex.CCall.retty != Ity_I64 && e->Iex.CCall.retty != Ity_I32) 1825ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown goto irreducible; 1826ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1827ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Marshal args, do the call. */ 1828436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov UInt addToSp = 0; 1829436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov RetLoc rloc = mk_RetLoc_INVALID(); 1830436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov doHelperCall( &addToSp, &rloc, env, NULL/*guard*/, 1831436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov e->Iex.CCall.cee, e->Iex.CCall.retty, e->Iex.CCall.args ); 1832436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov vassert(is_sane_RetLoc(rloc)); 1833436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov vassert(rloc.pri == RLPri_Int); 1834436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov vassert(addToSp == 0); 1835ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1836ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Move to dst, and zero out the top 32 bits if the result type is 1837ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Ity_I32. Probably overkill, but still .. */ 1838ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->Iex.CCall.retty == Ity_I64) 1839ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, mk_iMOVsd_RR(hregAMD64_RAX(), dst)); 1840ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown else 1841ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_MovxLQ(False, hregAMD64_RAX(), dst)); 1842ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1843ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return dst; 1844ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1845ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1846ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* --------- LITERAL --------- */ 1847ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* 64/32/16/8-bit literals */ 1848ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iex_Const: 1849ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (ty == Ity_I64) { 1850ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg r = newVRegI(env); 1851ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_Imm64(e->Iex.Const.con->Ico.U64, r)); 1852ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return r; 1853ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 1854ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown AMD64RMI* rmi = iselIntExpr_RMI ( env, e ); 1855ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg r = newVRegI(env); 1856ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_Alu64R(Aalu_MOV, rmi, r)); 1857ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return r; 1858ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1859ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1860ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* --------- MULTIPLEX --------- */ 1861436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case Iex_ITE: { // VFD 1862436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov if ((ty == Ity_I64 || ty == Ity_I32 || ty == Ity_I16 || ty == Ity_I8) 1863436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov && typeOfIRExpr(env->type_env,e->Iex.ITE.cond) == Ity_I1) { 1864436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov HReg r1 = iselIntExpr_R(env, e->Iex.ITE.iftrue); 1865436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov AMD64RM* r0 = iselIntExpr_RM(env, e->Iex.ITE.iffalse); 1866436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov HReg dst = newVRegI(env); 1867436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov addInstr(env, mk_iMOVsd_RR(r1,dst)); 1868436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov AMD64CondCode cc = iselCondCode(env, e->Iex.ITE.cond); 1869436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov addInstr(env, AMD64Instr_CMov64(cc ^ 1, r0, dst)); 1870436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov return dst; 1871ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1872ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 1873ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1874ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1875ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* --------- TERNARY OP --------- */ 1876ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iex_Triop: { 1877663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng IRTriop *triop = e->Iex.Triop.details; 1878ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* C3210 flags following FPU partial remainder (fprem), both 1879ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IEEE compliant (PREM1) and non-IEEE compliant (PREM). */ 1880663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng if (triop->op == Iop_PRemC3210F64 1881663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng || triop->op == Iop_PRem1C3210F64) { 1882ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown AMD64AMode* m8_rsp = AMD64AMode_IR(-8, hregAMD64_RSP()); 1883663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng HReg arg1 = iselDblExpr(env, triop->arg2); 1884663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng HReg arg2 = iselDblExpr(env, triop->arg3); 1885ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg dst = newVRegI(env); 1886ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_A87Free(2)); 1887ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1888ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* one arg -> top of x87 stack */ 1889ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_SseLdSt(False/*store*/, 8, arg2, m8_rsp)); 1890ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_A87PushPop(m8_rsp, True/*push*/, 8)); 1891ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1892ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* other arg -> top of x87 stack */ 1893ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_SseLdSt(False/*store*/, 8, arg1, m8_rsp)); 1894ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_A87PushPop(m8_rsp, True/*push*/, 8)); 1895ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1896663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng switch (triop->op) { 1897ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_PRemC3210F64: 1898ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_A87FpOp(Afp_PREM)); 1899ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 1900ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_PRem1C3210F64: 1901ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_A87FpOp(Afp_PREM1)); 1902ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 1903ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: 1904ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert(0); 1905ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1906ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Ignore the result, and instead make off with the FPU's 1907ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown C3210 flags (in the status word). */ 1908ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_A87StSW(m8_rsp)); 1909ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_Alu64R(Aalu_MOV,AMD64RMI_Mem(m8_rsp),dst)); 1910ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_Alu64R(Aalu_AND,AMD64RMI_Imm(0x4700),dst)); 1911ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return dst; 1912ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1913ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 1914ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1915ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1916ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: 1917ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 1918ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } /* switch (e->tag) */ 1919ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1920ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* We get here if no pattern matched. */ 1921ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown irreducible: 1922ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ppIRExpr(e); 1923ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vpanic("iselIntExpr_R(amd64): cannot reduce tree"); 1924ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1925ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1926ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1927ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------*/ 1928ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- ISEL: Integer expression auxiliaries ---*/ 1929ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------*/ 1930ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1931ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* --------------------- AMODEs --------------------- */ 1932ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1933ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Return an AMode which computes the value of the specified 1934ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown expression, possibly also adding insns to the code list as a 1935ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown result. The expression may only be a 32-bit one. 1936ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/ 1937ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1938ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic AMD64AMode* iselIntExpr_AMode ( ISelEnv* env, IRExpr* e ) 1939ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1940ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown AMD64AMode* am = iselIntExpr_AMode_wrk(env, e); 1941ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert(sane_AMode(am)); 1942ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return am; 1943ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1944ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1945ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* DO NOT CALL THIS DIRECTLY ! */ 1946ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic AMD64AMode* iselIntExpr_AMode_wrk ( ISelEnv* env, IRExpr* e ) 1947ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1948ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown MatchInfo mi; 1949ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DECLARE_PATTERN(p_complex); 1950ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRType ty = typeOfIRExpr(env->type_env,e); 1951ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert(ty == Ity_I64); 1952ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1953ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Add64( Add64(expr1, Shl64(expr2, imm8)), simm32 ) */ 1954ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* bind0 bind1 bind2 bind3 */ 1955ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEFINE_PATTERN(p_complex, 1956ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown binop( Iop_Add64, 1957ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown binop( Iop_Add64, 1958ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown bind(0), 1959ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown binop(Iop_Shl64, bind(1), bind(2)) 1960ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ), 1961ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown bind(3) 1962ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ) 1963ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ); 1964ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (matchIRExpr(&mi, p_complex, e)) { 1965ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRExpr* expr1 = mi.bindee[0]; 1966ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRExpr* expr2 = mi.bindee[1]; 1967ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRExpr* imm8 = mi.bindee[2]; 1968ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRExpr* simm32 = mi.bindee[3]; 1969ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (imm8->tag == Iex_Const 1970ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && imm8->Iex.Const.con->tag == Ico_U8 1971ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && imm8->Iex.Const.con->Ico.U8 < 4 1972ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* imm8 is OK, now check simm32 */ 1973ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && simm32->tag == Iex_Const 1974ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && simm32->Iex.Const.con->tag == Ico_U64 1975ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && fitsIn32Bits(simm32->Iex.Const.con->Ico.U64)) { 1976ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt shift = imm8->Iex.Const.con->Ico.U8; 1977ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt offset = toUInt(simm32->Iex.Const.con->Ico.U64); 1978ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg r1 = iselIntExpr_R(env, expr1); 1979ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg r2 = iselIntExpr_R(env, expr2); 1980ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert(shift == 0 || shift == 1 || shift == 2 || shift == 3); 1981ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return AMD64AMode_IRRS(offset, r1, r2, shift); 1982ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1983ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1984ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1985ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Add64(expr1, Shl64(expr2, imm)) */ 1986ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->tag == Iex_Binop 1987ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && e->Iex.Binop.op == Iop_Add64 1988ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && e->Iex.Binop.arg2->tag == Iex_Binop 1989ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && e->Iex.Binop.arg2->Iex.Binop.op == Iop_Shl64 1990ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && e->Iex.Binop.arg2->Iex.Binop.arg2->tag == Iex_Const 1991ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && e->Iex.Binop.arg2->Iex.Binop.arg2->Iex.Const.con->tag == Ico_U8) { 1992ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt shift = e->Iex.Binop.arg2->Iex.Binop.arg2->Iex.Const.con->Ico.U8; 1993ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (shift == 1 || shift == 2 || shift == 3) { 1994ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg r1 = iselIntExpr_R(env, e->Iex.Binop.arg1); 1995ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg r2 = iselIntExpr_R(env, e->Iex.Binop.arg2->Iex.Binop.arg1 ); 1996ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return AMD64AMode_IRRS(0, r1, r2, shift); 1997ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1998ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1999ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2000ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Add64(expr,i) */ 2001ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->tag == Iex_Binop 2002ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && e->Iex.Binop.op == Iop_Add64 2003ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && e->Iex.Binop.arg2->tag == Iex_Const 2004ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && e->Iex.Binop.arg2->Iex.Const.con->tag == Ico_U64 2005ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && fitsIn32Bits(e->Iex.Binop.arg2->Iex.Const.con->Ico.U64)) { 2006ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg r1 = iselIntExpr_R(env, e->Iex.Binop.arg1); 2007ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return AMD64AMode_IR( 2008ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown toUInt(e->Iex.Binop.arg2->Iex.Const.con->Ico.U64), 2009ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown r1 2010ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ); 2011ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2012ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2013ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Doesn't match anything in particular. Generate it into 2014ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown a register and use that. */ 2015ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown { 2016ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg r1 = iselIntExpr_R(env, e); 2017ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return AMD64AMode_IR(0, r1); 2018ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2019ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 2020ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2021ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2022ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* --------------------- RMIs --------------------- */ 2023ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2024ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Similarly, calculate an expression into an X86RMI operand. As with 2025ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown iselIntExpr_R, the expression can have type 32, 16 or 8 bits. */ 2026ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2027ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic AMD64RMI* iselIntExpr_RMI ( ISelEnv* env, IRExpr* e ) 2028ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 2029ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown AMD64RMI* rmi = iselIntExpr_RMI_wrk(env, e); 2030ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* sanity checks ... */ 2031ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (rmi->tag) { 2032ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Armi_Imm: 2033ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return rmi; 2034ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Armi_Reg: 2035ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert(hregClass(rmi->Armi.Reg.reg) == HRcInt64); 2036ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert(hregIsVirtual(rmi->Armi.Reg.reg)); 2037ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return rmi; 2038ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Armi_Mem: 2039ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert(sane_AMode(rmi->Armi.Mem.am)); 2040ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return rmi; 2041ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: 2042ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vpanic("iselIntExpr_RMI: unknown amd64 RMI tag"); 2043ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2044ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 2045ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2046ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* DO NOT CALL THIS DIRECTLY ! */ 2047ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic AMD64RMI* iselIntExpr_RMI_wrk ( ISelEnv* env, IRExpr* e ) 2048ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 2049ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRType ty = typeOfIRExpr(env->type_env,e); 2050ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert(ty == Ity_I64 || ty == Ity_I32 2051ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown || ty == Ity_I16 || ty == Ity_I8); 2052ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2053ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* special case: immediate 64/32/16/8 */ 2054ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->tag == Iex_Const) { 2055ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (e->Iex.Const.con->tag) { 2056ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Ico_U64: 2057ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (fitsIn32Bits(e->Iex.Const.con->Ico.U64)) { 2058ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return AMD64RMI_Imm(toUInt(e->Iex.Const.con->Ico.U64)); 2059ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2060ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 2061ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Ico_U32: 2062ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return AMD64RMI_Imm(e->Iex.Const.con->Ico.U32); break; 2063ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Ico_U16: 2064ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return AMD64RMI_Imm(0xFFFF & e->Iex.Const.con->Ico.U16); break; 2065ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Ico_U8: 2066ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return AMD64RMI_Imm(0xFF & e->Iex.Const.con->Ico.U8); break; 2067ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: 2068ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vpanic("iselIntExpr_RMI.Iex_Const(amd64)"); 2069ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2070ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2071ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2072ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* special case: 64-bit GET */ 2073ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->tag == Iex_Get && ty == Ity_I64) { 2074ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return AMD64RMI_Mem(AMD64AMode_IR(e->Iex.Get.offset, 2075ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown hregAMD64_RBP())); 2076ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2077ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2078ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* special case: 64-bit load from memory */ 2079ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->tag == Iex_Load && ty == Ity_I64 2080ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && e->Iex.Load.end == Iend_LE) { 2081ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown AMD64AMode* am = iselIntExpr_AMode(env, e->Iex.Load.addr); 2082ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return AMD64RMI_Mem(am); 2083ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2084ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2085ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* default case: calculate into a register and return that */ 2086ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown { 2087ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg r = iselIntExpr_R ( env, e ); 2088ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return AMD64RMI_Reg(r); 2089ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2090ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 2091ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2092ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2093ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* --------------------- RIs --------------------- */ 2094ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2095ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Calculate an expression into an AMD64RI operand. As with 2096ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown iselIntExpr_R, the expression can have type 64, 32, 16 or 8 2097ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown bits. */ 2098ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2099ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic AMD64RI* iselIntExpr_RI ( ISelEnv* env, IRExpr* e ) 2100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 2101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown AMD64RI* ri = iselIntExpr_RI_wrk(env, e); 2102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* sanity checks ... */ 2103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (ri->tag) { 2104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Ari_Imm: 2105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return ri; 2106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Ari_Reg: 2107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert(hregClass(ri->Ari.Reg.reg) == HRcInt64); 2108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert(hregIsVirtual(ri->Ari.Reg.reg)); 2109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return ri; 2110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: 2111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vpanic("iselIntExpr_RI: unknown amd64 RI tag"); 2112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 2114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* DO NOT CALL THIS DIRECTLY ! */ 2116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic AMD64RI* iselIntExpr_RI_wrk ( ISelEnv* env, IRExpr* e ) 2117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 2118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRType ty = typeOfIRExpr(env->type_env,e); 2119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert(ty == Ity_I64 || ty == Ity_I32 2120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown || ty == Ity_I16 || ty == Ity_I8); 2121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* special case: immediate */ 2123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->tag == Iex_Const) { 2124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (e->Iex.Const.con->tag) { 2125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Ico_U64: 2126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (fitsIn32Bits(e->Iex.Const.con->Ico.U64)) { 2127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return AMD64RI_Imm(toUInt(e->Iex.Const.con->Ico.U64)); 2128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 2130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Ico_U32: 2131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return AMD64RI_Imm(e->Iex.Const.con->Ico.U32); 2132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Ico_U16: 2133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return AMD64RI_Imm(0xFFFF & e->Iex.Const.con->Ico.U16); 2134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Ico_U8: 2135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return AMD64RI_Imm(0xFF & e->Iex.Const.con->Ico.U8); 2136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: 2137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vpanic("iselIntExpr_RMI.Iex_Const(amd64)"); 2138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* default case: calculate into a register and return that */ 2142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown { 2143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg r = iselIntExpr_R ( env, e ); 2144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return AMD64RI_Reg(r); 2145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 2147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* --------------------- RMs --------------------- */ 2150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Similarly, calculate an expression into an AMD64RM operand. As 2152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown with iselIntExpr_R, the expression can have type 64, 32, 16 or 8 2153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown bits. */ 2154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic AMD64RM* iselIntExpr_RM ( ISelEnv* env, IRExpr* e ) 2156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 2157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown AMD64RM* rm = iselIntExpr_RM_wrk(env, e); 2158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* sanity checks ... */ 2159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (rm->tag) { 2160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Arm_Reg: 2161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert(hregClass(rm->Arm.Reg.reg) == HRcInt64); 2162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert(hregIsVirtual(rm->Arm.Reg.reg)); 2163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return rm; 2164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Arm_Mem: 2165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert(sane_AMode(rm->Arm.Mem.am)); 2166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return rm; 2167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: 2168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vpanic("iselIntExpr_RM: unknown amd64 RM tag"); 2169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 2171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* DO NOT CALL THIS DIRECTLY ! */ 2173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic AMD64RM* iselIntExpr_RM_wrk ( ISelEnv* env, IRExpr* e ) 2174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 2175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRType ty = typeOfIRExpr(env->type_env,e); 2176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert(ty == Ity_I64 || ty == Ity_I32 || ty == Ity_I16 || ty == Ity_I8); 2177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* special case: 64-bit GET */ 2179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->tag == Iex_Get && ty == Ity_I64) { 2180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return AMD64RM_Mem(AMD64AMode_IR(e->Iex.Get.offset, 2181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown hregAMD64_RBP())); 2182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* special case: load from memory */ 2185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* default case: calculate into a register and return that */ 2187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown { 2188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg r = iselIntExpr_R ( env, e ); 2189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return AMD64RM_Reg(r); 2190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 2192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* --------------------- CONDCODE --------------------- */ 2195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Generate code to evaluated a bit-typed expression, returning the 2197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown condition code which would correspond when the expression would 2198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown notionally have returned 1. */ 2199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic AMD64CondCode iselCondCode ( ISelEnv* env, IRExpr* e ) 2201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 2202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Uh, there's nothing we can sanity check here, unfortunately. */ 2203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return iselCondCode_wrk(env,e); 2204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 2205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* DO NOT CALL THIS DIRECTLY ! */ 2207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic AMD64CondCode iselCondCode_wrk ( ISelEnv* env, IRExpr* e ) 2208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 2209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown MatchInfo mi; 2210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert(e); 2212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert(typeOfIRExpr(env->type_env,e) == Ity_I1); 2213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* var */ 2215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->tag == Iex_RdTmp) { 2216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg r64 = lookupIRTemp(env, e->Iex.RdTmp.tmp); 2217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg dst = newVRegI(env); 2218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, mk_iMOVsd_RR(r64,dst)); 2219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_Alu64R(Aalu_AND,AMD64RMI_Imm(1),dst)); 2220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return Acc_NZ; 2221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Constant 1:Bit */ 2224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->tag == Iex_Const) { 2225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg r; 2226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert(e->Iex.Const.con->tag == Ico_U1); 2227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert(e->Iex.Const.con->Ico.U1 == True 2228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown || e->Iex.Const.con->Ico.U1 == False); 2229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown r = newVRegI(env); 2230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_Alu64R(Aalu_MOV,AMD64RMI_Imm(0),r)); 2231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_Alu64R(Aalu_XOR,AMD64RMI_Reg(r),r)); 2232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return e->Iex.Const.con->Ico.U1 ? Acc_Z : Acc_NZ; 2233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Not1(...) */ 2236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->tag == Iex_Unop && e->Iex.Unop.op == Iop_Not1) { 2237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Generate code for the arg, and negate the test condition */ 2238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return 1 ^ iselCondCode(env, e->Iex.Unop.arg); 2239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* --- patterns rooted at: 64to1 --- */ 2242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* 64to1 */ 2244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->tag == Iex_Unop && e->Iex.Unop.op == Iop_64to1) { 2245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg reg = iselIntExpr_R(env, e->Iex.Unop.arg); 2246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_Test64(1,reg)); 2247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return Acc_NZ; 2248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2250663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng /* --- patterns rooted at: 32to1 --- */ 2251663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 2252663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng /* 32to1 */ 2253663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng if (e->tag == Iex_Unop && e->Iex.Unop.op == Iop_32to1) { 2254663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng HReg reg = iselIntExpr_R(env, e->Iex.Unop.arg); 2255663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng addInstr(env, AMD64Instr_Test64(1,reg)); 2256663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng return Acc_NZ; 2257663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng } 2258663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 2259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* --- patterns rooted at: CmpNEZ8 --- */ 2260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* CmpNEZ8(x) */ 2262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->tag == Iex_Unop 2263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && e->Iex.Unop.op == Iop_CmpNEZ8) { 2264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg r = iselIntExpr_R(env, e->Iex.Unop.arg); 2265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_Test64(0xFF,r)); 2266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return Acc_NZ; 2267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* --- patterns rooted at: CmpNEZ16 --- */ 2270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* CmpNEZ16(x) */ 2272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->tag == Iex_Unop 2273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && e->Iex.Unop.op == Iop_CmpNEZ16) { 2274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg r = iselIntExpr_R(env, e->Iex.Unop.arg); 2275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_Test64(0xFFFF,r)); 2276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return Acc_NZ; 2277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* --- patterns rooted at: CmpNEZ32 --- */ 2280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* CmpNEZ32(x) */ 2282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->tag == Iex_Unop 2283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && e->Iex.Unop.op == Iop_CmpNEZ32) { 2284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg r1 = iselIntExpr_R(env, e->Iex.Unop.arg); 2285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown AMD64RMI* rmi2 = AMD64RMI_Imm(0); 2286b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov addInstr(env, AMD64Instr_Alu32R(Aalu_CMP,rmi2,r1)); 2287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return Acc_NZ; 2288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* --- patterns rooted at: CmpNEZ64 --- */ 2291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* CmpNEZ64(Or64(x,y)) */ 2293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown { 2294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DECLARE_PATTERN(p_CmpNEZ64_Or64); 2295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEFINE_PATTERN(p_CmpNEZ64_Or64, 2296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown unop(Iop_CmpNEZ64, binop(Iop_Or64, bind(0), bind(1)))); 2297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (matchIRExpr(&mi, p_CmpNEZ64_Or64, e)) { 2298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg r0 = iselIntExpr_R(env, mi.bindee[0]); 2299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown AMD64RMI* rmi1 = iselIntExpr_RMI(env, mi.bindee[1]); 2300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg tmp = newVRegI(env); 2301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, mk_iMOVsd_RR(r0, tmp)); 2302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_Alu64R(Aalu_OR,rmi1,tmp)); 2303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return Acc_NZ; 2304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* CmpNEZ64(x) */ 2308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->tag == Iex_Unop 2309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && e->Iex.Unop.op == Iop_CmpNEZ64) { 2310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg r1 = iselIntExpr_R(env, e->Iex.Unop.arg); 2311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown AMD64RMI* rmi2 = AMD64RMI_Imm(0); 2312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_Alu64R(Aalu_CMP,rmi2,r1)); 2313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return Acc_NZ; 2314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* --- patterns rooted at: Cmp{EQ,NE}{8,16,32} --- */ 2317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* CmpEQ8 / CmpNE8 */ 2319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->tag == Iex_Binop 2320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && (e->Iex.Binop.op == Iop_CmpEQ8 2321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown || e->Iex.Binop.op == Iop_CmpNE8 2322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown || e->Iex.Binop.op == Iop_CasCmpEQ8 2323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown || e->Iex.Binop.op == Iop_CasCmpNE8)) { 2324436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov if (isZeroU8(e->Iex.Binop.arg2)) { 2325436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov HReg r1 = iselIntExpr_R(env, e->Iex.Binop.arg1); 2326436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov addInstr(env, AMD64Instr_Test64(0xFF,r1)); 2327436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov switch (e->Iex.Binop.op) { 2328436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case Iop_CmpEQ8: case Iop_CasCmpEQ8: return Acc_Z; 2329436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case Iop_CmpNE8: case Iop_CasCmpNE8: return Acc_NZ; 2330436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov default: vpanic("iselCondCode(amd64): CmpXX8(expr,0:I8)"); 2331436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } 2332436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } else { 2333436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov HReg r1 = iselIntExpr_R(env, e->Iex.Binop.arg1); 2334436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov AMD64RMI* rmi2 = iselIntExpr_RMI(env, e->Iex.Binop.arg2); 2335436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov HReg r = newVRegI(env); 2336436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov addInstr(env, mk_iMOVsd_RR(r1,r)); 2337436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov addInstr(env, AMD64Instr_Alu64R(Aalu_XOR,rmi2,r)); 2338436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov addInstr(env, AMD64Instr_Alu64R(Aalu_AND,AMD64RMI_Imm(0xFF),r)); 2339436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov switch (e->Iex.Binop.op) { 2340436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case Iop_CmpEQ8: case Iop_CasCmpEQ8: return Acc_Z; 2341436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case Iop_CmpNE8: case Iop_CasCmpNE8: return Acc_NZ; 2342436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov default: vpanic("iselCondCode(amd64): CmpXX8(expr,expr)"); 2343436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } 2344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* CmpEQ16 / CmpNE16 */ 2348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->tag == Iex_Binop 2349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && (e->Iex.Binop.op == Iop_CmpEQ16 2350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown || e->Iex.Binop.op == Iop_CmpNE16 2351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown || e->Iex.Binop.op == Iop_CasCmpEQ16 2352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown || e->Iex.Binop.op == Iop_CasCmpNE16)) { 2353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg r1 = iselIntExpr_R(env, e->Iex.Binop.arg1); 2354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown AMD64RMI* rmi2 = iselIntExpr_RMI(env, e->Iex.Binop.arg2); 2355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg r = newVRegI(env); 2356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, mk_iMOVsd_RR(r1,r)); 2357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_Alu64R(Aalu_XOR,rmi2,r)); 2358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_Alu64R(Aalu_AND,AMD64RMI_Imm(0xFFFF),r)); 2359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (e->Iex.Binop.op) { 2360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CmpEQ16: case Iop_CasCmpEQ16: return Acc_Z; 2361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CmpNE16: case Iop_CasCmpNE16: return Acc_NZ; 2362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: vpanic("iselCondCode(amd64): CmpXX16"); 2363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2366b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov /* CmpNE64(ccall, 64-bit constant) (--smc-check=all optimisation). 2367b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov Saves a "movq %rax, %tmp" compared to the default route. */ 2368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->tag == Iex_Binop 2369b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov && e->Iex.Binop.op == Iop_CmpNE64 2370b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov && e->Iex.Binop.arg1->tag == Iex_CCall 2371b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov && e->Iex.Binop.arg2->tag == Iex_Const) { 2372b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov IRExpr* cal = e->Iex.Binop.arg1; 2373b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov IRExpr* con = e->Iex.Binop.arg2; 2374b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov HReg tmp = newVRegI(env); 2375b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov /* clone & partial-eval of generic Iex_CCall and Iex_Const cases */ 2376b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov vassert(cal->Iex.CCall.retty == Ity_I64); /* else ill-typed IR */ 2377b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov vassert(con->Iex.Const.con->tag == Ico_U64); 2378b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov /* Marshal args, do the call. */ 2379436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov UInt addToSp = 0; 2380436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov RetLoc rloc = mk_RetLoc_INVALID(); 2381436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov doHelperCall( &addToSp, &rloc, env, NULL/*guard*/, 2382436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov cal->Iex.CCall.cee, 2383436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov cal->Iex.CCall.retty, cal->Iex.CCall.args ); 2384436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov vassert(is_sane_RetLoc(rloc)); 2385436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov vassert(rloc.pri == RLPri_Int); 2386436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov vassert(addToSp == 0); 2387436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /* */ 2388b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov addInstr(env, AMD64Instr_Imm64(con->Iex.Const.con->Ico.U64, tmp)); 2389b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov addInstr(env, AMD64Instr_Alu64R(Aalu_CMP, 2390b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov AMD64RMI_Reg(hregAMD64_RAX()), tmp)); 2391b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov return Acc_NZ; 2392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Cmp*64*(x,y) */ 2395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->tag == Iex_Binop 2396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && (e->Iex.Binop.op == Iop_CmpEQ64 2397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown || e->Iex.Binop.op == Iop_CmpNE64 2398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown || e->Iex.Binop.op == Iop_CmpLT64S 2399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown || e->Iex.Binop.op == Iop_CmpLT64U 2400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown || e->Iex.Binop.op == Iop_CmpLE64S 2401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown || e->Iex.Binop.op == Iop_CmpLE64U 2402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown || e->Iex.Binop.op == Iop_CasCmpEQ64 2403436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov || e->Iex.Binop.op == Iop_CasCmpNE64 2404436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov || e->Iex.Binop.op == Iop_ExpCmpNE64)) { 2405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg r1 = iselIntExpr_R(env, e->Iex.Binop.arg1); 2406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown AMD64RMI* rmi2 = iselIntExpr_RMI(env, e->Iex.Binop.arg2); 2407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_Alu64R(Aalu_CMP,rmi2,r1)); 2408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (e->Iex.Binop.op) { 2409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CmpEQ64: case Iop_CasCmpEQ64: return Acc_Z; 2410436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case Iop_CmpNE64: 2411436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case Iop_CasCmpNE64: case Iop_ExpCmpNE64: return Acc_NZ; 2412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CmpLT64S: return Acc_L; 2413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CmpLT64U: return Acc_B; 2414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CmpLE64S: return Acc_LE; 2415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CmpLE64U: return Acc_BE; 2416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: vpanic("iselCondCode(amd64): CmpXX64"); 2417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2420b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov /* Cmp*32*(x,y) */ 2421b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (e->tag == Iex_Binop 2422b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov && (e->Iex.Binop.op == Iop_CmpEQ32 2423b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov || e->Iex.Binop.op == Iop_CmpNE32 2424b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov || e->Iex.Binop.op == Iop_CmpLT32S 2425b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov || e->Iex.Binop.op == Iop_CmpLT32U 2426b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov || e->Iex.Binop.op == Iop_CmpLE32S 2427b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov || e->Iex.Binop.op == Iop_CmpLE32U 2428b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov || e->Iex.Binop.op == Iop_CasCmpEQ32 2429436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov || e->Iex.Binop.op == Iop_CasCmpNE32 2430436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov || e->Iex.Binop.op == Iop_ExpCmpNE32)) { 2431b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov HReg r1 = iselIntExpr_R(env, e->Iex.Binop.arg1); 2432b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov AMD64RMI* rmi2 = iselIntExpr_RMI(env, e->Iex.Binop.arg2); 2433b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov addInstr(env, AMD64Instr_Alu32R(Aalu_CMP,rmi2,r1)); 2434b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov switch (e->Iex.Binop.op) { 2435b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov case Iop_CmpEQ32: case Iop_CasCmpEQ32: return Acc_Z; 2436436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case Iop_CmpNE32: 2437436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case Iop_CasCmpNE32: case Iop_ExpCmpNE32: return Acc_NZ; 2438b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov case Iop_CmpLT32S: return Acc_L; 2439b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov case Iop_CmpLT32U: return Acc_B; 2440b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov case Iop_CmpLE32S: return Acc_LE; 2441b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov case Iop_CmpLE32U: return Acc_BE; 2442b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov default: vpanic("iselCondCode(amd64): CmpXX32"); 2443b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } 2444b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } 2445b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 2446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ppIRExpr(e); 2447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vpanic("iselCondCode(amd64)"); 2448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 2449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------*/ 2452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- ISEL: Integer expressions (128 bit) ---*/ 2453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------*/ 2454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Compute a 128-bit value into a register pair, which is returned as 2456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown the first two parameters. As with iselIntExpr_R, these may be 2457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown either real or virtual regs; in any case they must not be changed 2458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown by subsequent code emitted by the caller. */ 2459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void iselInt128Expr ( HReg* rHi, HReg* rLo, 2461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ISelEnv* env, IRExpr* e ) 2462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 2463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown iselInt128Expr_wrk(rHi, rLo, env, e); 2464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# if 0 2465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vex_printf("\n"); ppIRExpr(e); vex_printf("\n"); 2466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 2467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert(hregClass(*rHi) == HRcInt64); 2468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert(hregIsVirtual(*rHi)); 2469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert(hregClass(*rLo) == HRcInt64); 2470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert(hregIsVirtual(*rLo)); 2471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 2472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* DO NOT CALL THIS DIRECTLY ! */ 2474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void iselInt128Expr_wrk ( HReg* rHi, HReg* rLo, 2475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ISelEnv* env, IRExpr* e ) 2476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 2477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert(e); 2478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert(typeOfIRExpr(env->type_env,e) == Ity_I128); 2479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* read 128-bit IRTemp */ 2481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->tag == Iex_RdTmp) { 2482663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng lookupIRTempPair( rHi, rLo, env, e->Iex.RdTmp.tmp); 2483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return; 2484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* --------- BINARY ops --------- */ 2487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->tag == Iex_Binop) { 2488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (e->Iex.Binop.op) { 2489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* 64 x 64 -> 128 multiply */ 2490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_MullU64: 2491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_MullS64: { 2492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* get one operand into %rax, and the other into a R/M. 2493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Need to make an educated guess about which is better in 2494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown which. */ 2495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg tLo = newVRegI(env); 2496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg tHi = newVRegI(env); 2497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bool syned = toBool(e->Iex.Binop.op == Iop_MullS64); 2498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown AMD64RM* rmLeft = iselIntExpr_RM(env, e->Iex.Binop.arg1); 2499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg rRight = iselIntExpr_R(env, e->Iex.Binop.arg2); 2500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, mk_iMOVsd_RR(rRight, hregAMD64_RAX())); 2501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_MulL(syned, rmLeft)); 2502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Result is now in RDX:RAX. Tell the caller. */ 2503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, mk_iMOVsd_RR(hregAMD64_RDX(), tHi)); 2504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, mk_iMOVsd_RR(hregAMD64_RAX(), tLo)); 2505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *rHi = tHi; 2506ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *rLo = tLo; 2507ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return; 2508ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* 128 x 64 -> (64(rem),64(div)) division */ 2511ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_DivModU128to64: 2512ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_DivModS128to64: { 2513ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Get the 128-bit operand into rdx:rax, and the other into 2514ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown any old R/M. */ 2515ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg sHi, sLo; 2516ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg tLo = newVRegI(env); 2517ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg tHi = newVRegI(env); 2518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bool syned = toBool(e->Iex.Binop.op == Iop_DivModS128to64); 2519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown AMD64RM* rmRight = iselIntExpr_RM(env, e->Iex.Binop.arg2); 2520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown iselInt128Expr(&sHi,&sLo, env, e->Iex.Binop.arg1); 2521ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, mk_iMOVsd_RR(sHi, hregAMD64_RDX())); 2522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, mk_iMOVsd_RR(sLo, hregAMD64_RAX())); 2523ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_Div(syned, 8, rmRight)); 2524ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, mk_iMOVsd_RR(hregAMD64_RDX(), tHi)); 2525ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, mk_iMOVsd_RR(hregAMD64_RAX(), tLo)); 2526ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *rHi = tHi; 2527ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *rLo = tLo; 2528ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return; 2529ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2530ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2531ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* 64HLto128(e1,e2) */ 2532ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_64HLto128: 2533ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *rHi = iselIntExpr_R(env, e->Iex.Binop.arg1); 2534ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *rLo = iselIntExpr_R(env, e->Iex.Binop.arg2); 2535ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return; 2536ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2537ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: 2538ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 2539ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2540ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } /* if (e->tag == Iex_Binop) */ 2541ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2542ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ppIRExpr(e); 2543ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vpanic("iselInt128Expr"); 2544ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 2545ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2546ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2547ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------*/ 2548ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- ISEL: Floating point expressions (32 bit) ---*/ 2549ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------*/ 2550ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2551ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Nothing interesting here; really just wrappers for 2552ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 64-bit stuff. */ 2553ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2554ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic HReg iselFltExpr ( ISelEnv* env, IRExpr* e ) 2555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 2556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg r = iselFltExpr_wrk( env, e ); 2557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# if 0 2558ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vex_printf("\n"); ppIRExpr(e); vex_printf("\n"); 2559ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 2560ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert(hregClass(r) == HRcVec128); 2561ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert(hregIsVirtual(r)); 2562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return r; 2563ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 2564ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2565ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* DO NOT CALL THIS DIRECTLY */ 2566ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic HReg iselFltExpr_wrk ( ISelEnv* env, IRExpr* e ) 2567ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 2568ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRType ty = typeOfIRExpr(env->type_env,e); 2569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert(ty == Ity_F32); 2570ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2571ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->tag == Iex_RdTmp) { 2572ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return lookupIRTemp(env, e->Iex.RdTmp.tmp); 2573ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2574ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->tag == Iex_Load && e->Iex.Load.end == Iend_LE) { 2576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown AMD64AMode* am; 2577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegV(env); 2578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert(e->Iex.Load.ty == Ity_F32); 2579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown am = iselIntExpr_AMode(env, e->Iex.Load.addr); 2580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_SseLdSt(True/*load*/, 4, res, am)); 2581ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 2582ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2584ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->tag == Iex_Binop 2585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && e->Iex.Binop.op == Iop_F64toF32) { 2586ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Although the result is still held in a standard SSE register, 2587ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown we need to round it to reflect the loss of accuracy/range 2588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown entailed in casting it to a 32-bit float. */ 2589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg dst = newVRegV(env); 2590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg src = iselDblExpr(env, e->Iex.Binop.arg2); 2591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown set_SSE_rounding_mode( env, e->Iex.Binop.arg1 ); 2592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_SseSDSS(True/*D->S*/,src,dst)); 2593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown set_SSE_rounding_default( env ); 2594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return dst; 2595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->tag == Iex_Get) { 2598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown AMD64AMode* am = AMD64AMode_IR( e->Iex.Get.offset, 2599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown hregAMD64_RBP() ); 2600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegV(env); 2601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_SseLdSt( True/*load*/, 4, res, am )); 2602ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 2603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2605ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->tag == Iex_Unop 2606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && e->Iex.Unop.op == Iop_ReinterpI32asF32) { 2607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Given an I32, produce an IEEE754 float with the same bit 2608ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pattern. */ 2609ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg dst = newVRegV(env); 2610ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg src = iselIntExpr_R(env, e->Iex.Unop.arg); 2611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown AMD64AMode* m4_rsp = AMD64AMode_IR(-4, hregAMD64_RSP()); 2612ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_Store(4, src, m4_rsp)); 2613ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_SseLdSt( True/*load*/, 4, dst, m4_rsp )); 2614ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return dst; 2615ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2616ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2617ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->tag == Iex_Binop && e->Iex.Binop.op == Iop_RoundF32toInt) { 2618ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown AMD64AMode* m8_rsp = AMD64AMode_IR(-8, hregAMD64_RSP()); 2619ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg arg = iselFltExpr(env, e->Iex.Binop.arg2); 2620ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg dst = newVRegV(env); 2621ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2622ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* rf now holds the value to be rounded. The first thing to do 2623ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown is set the FPU's rounding mode accordingly. */ 2624ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2625ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Set host x87 rounding mode */ 2626ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown set_FPU_rounding_mode( env, e->Iex.Binop.arg1 ); 2627ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2628ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_SseLdSt(False/*store*/, 4, arg, m8_rsp)); 2629ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_A87Free(1)); 2630ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_A87PushPop(m8_rsp, True/*push*/, 4)); 2631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_A87FpOp(Afp_ROUND)); 2632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_A87PushPop(m8_rsp, False/*pop*/, 4)); 2633ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_SseLdSt(True/*load*/, 4, dst, m8_rsp)); 2634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Restore default x87 rounding. */ 2636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown set_FPU_rounding_default( env ); 2637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2638ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return dst; 2639ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2640ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2641436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov if (e->tag == Iex_Unop && e->Iex.Unop.op == Iop_NegF32) { 2642436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /* Sigh ... very rough code. Could do much better. */ 2643436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /* Get the 128-bit literal 00---0 10---0 into a register 2644436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov and xor it with the value to be negated. */ 2645436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov HReg r1 = newVRegI(env); 2646436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov HReg dst = newVRegV(env); 2647436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov HReg tmp = newVRegV(env); 2648436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov HReg src = iselFltExpr(env, e->Iex.Unop.arg); 2649436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov AMD64AMode* rsp0 = AMD64AMode_IR(0, hregAMD64_RSP()); 2650436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov addInstr(env, mk_vMOVsd_RR(src,tmp)); 2651436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov addInstr(env, AMD64Instr_Push(AMD64RMI_Imm(0))); 2652436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov addInstr(env, AMD64Instr_Imm64( 1ULL<<31, r1 )); 2653436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov addInstr(env, AMD64Instr_Push(AMD64RMI_Reg(r1))); 2654436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov addInstr(env, AMD64Instr_SseLdSt(True, 16, dst, rsp0)); 2655436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov addInstr(env, AMD64Instr_SseReRg(Asse_XOR, tmp, dst)); 2656436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov add_to_rsp(env, 16); 2657436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov return dst; 2658436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } 2659436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 2660436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov if (e->tag == Iex_Qop && e->Iex.Qop.details->op == Iop_MAddF32) { 2661436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov IRQop *qop = e->Iex.Qop.details; 2662436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov HReg dst = newVRegV(env); 2663436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov HReg argX = iselFltExpr(env, qop->arg2); 2664436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov HReg argY = iselFltExpr(env, qop->arg3); 2665436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov HReg argZ = iselFltExpr(env, qop->arg4); 2666436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /* XXXROUNDINGFIXME */ 2667436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /* set roundingmode here */ 2668436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /* subq $16, %rsp -- make a space*/ 2669436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov sub_from_rsp(env, 16); 2670436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /* Prepare 4 arg regs: 2671436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov leaq 0(%rsp), %rdi 2672436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov leaq 4(%rsp), %rsi 2673436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov leaq 8(%rsp), %rdx 2674436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov leaq 12(%rsp), %rcx 2675436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov */ 2676436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov addInstr(env, AMD64Instr_Lea64(AMD64AMode_IR(0, hregAMD64_RSP()), 2677436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov hregAMD64_RDI())); 2678436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov addInstr(env, AMD64Instr_Lea64(AMD64AMode_IR(4, hregAMD64_RSP()), 2679436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov hregAMD64_RSI())); 2680436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov addInstr(env, AMD64Instr_Lea64(AMD64AMode_IR(8, hregAMD64_RSP()), 2681436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov hregAMD64_RDX())); 2682436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov addInstr(env, AMD64Instr_Lea64(AMD64AMode_IR(12, hregAMD64_RSP()), 2683436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov hregAMD64_RCX())); 2684436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /* Store the three args, at (%rsi), (%rdx) and (%rcx): 2685436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov movss %argX, 0(%rsi) 2686436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov movss %argY, 0(%rdx) 2687436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov movss %argZ, 0(%rcx) 2688436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov */ 2689436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov addInstr(env, AMD64Instr_SseLdSt(False/*!isLoad*/, 4, argX, 2690436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov AMD64AMode_IR(0, hregAMD64_RSI()))); 2691436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov addInstr(env, AMD64Instr_SseLdSt(False/*!isLoad*/, 4, argY, 2692436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov AMD64AMode_IR(0, hregAMD64_RDX()))); 2693436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov addInstr(env, AMD64Instr_SseLdSt(False/*!isLoad*/, 4, argZ, 2694436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov AMD64AMode_IR(0, hregAMD64_RCX()))); 2695436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /* call the helper */ 2696436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov addInstr(env, AMD64Instr_Call( Acc_ALWAYS, 2697436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov (ULong)(HWord)h_generic_calc_MAddF32, 2698436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 4, mk_RetLoc_simple(RLPri_None) )); 2699436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /* fetch the result from memory, using %r_argp, which the 2700436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov register allocator will keep alive across the call. */ 2701436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov addInstr(env, AMD64Instr_SseLdSt(True/*isLoad*/, 4, dst, 2702436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov AMD64AMode_IR(0, hregAMD64_RSP()))); 2703436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /* and finally, clear the space */ 2704436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov add_to_rsp(env, 16); 2705436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov return dst; 2706436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } 2707436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 2708ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ppIRExpr(e); 2709ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vpanic("iselFltExpr_wrk"); 2710ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 2711ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2712ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2713ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------*/ 2714ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- ISEL: Floating point expressions (64 bit) ---*/ 2715ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------*/ 2716ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2717ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Compute a 64-bit floating point value into the lower half of an xmm 2718ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown register, the identity of which is returned. As with 2719ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown iselIntExpr_R, the returned reg will be virtual, and it must not be 2720ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown changed by subsequent code emitted by the caller. 2721ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/ 2722ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2723ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* IEEE 754 formats. From http://www.freesoft.org/CIE/RFC/1832/32.htm: 2724ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2725ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Type S (1 bit) E (11 bits) F (52 bits) 2726ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ---- --------- ----------- ----------- 2727ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown signalling NaN u 2047 (max) .0uuuuu---u 2728ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (with at least 2729ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown one 1 bit) 2730ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown quiet NaN u 2047 (max) .1uuuuu---u 2731ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2732ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown negative infinity 1 2047 (max) .000000---0 2733ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2734ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown positive infinity 0 2047 (max) .000000---0 2735ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2736ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown negative zero 1 0 .000000---0 2737ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2738ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown positive zero 0 0 .000000---0 2739ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/ 2740ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2741ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic HReg iselDblExpr ( ISelEnv* env, IRExpr* e ) 2742ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 2743ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg r = iselDblExpr_wrk( env, e ); 2744ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# if 0 2745ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vex_printf("\n"); ppIRExpr(e); vex_printf("\n"); 2746ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 2747ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert(hregClass(r) == HRcVec128); 2748ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert(hregIsVirtual(r)); 2749ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return r; 2750ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 2751ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2752ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* DO NOT CALL THIS DIRECTLY */ 2753ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic HReg iselDblExpr_wrk ( ISelEnv* env, IRExpr* e ) 2754ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 2755ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRType ty = typeOfIRExpr(env->type_env,e); 2756ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert(e); 2757ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert(ty == Ity_F64); 2758ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2759ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->tag == Iex_RdTmp) { 2760ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return lookupIRTemp(env, e->Iex.RdTmp.tmp); 2761ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2762ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2763ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->tag == Iex_Const) { 2764ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown union { ULong u64; Double f64; } u; 2765ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegV(env); 2766ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg tmp = newVRegI(env); 2767ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert(sizeof(u) == 8); 2768ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert(sizeof(u.u64) == 8); 2769ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert(sizeof(u.f64) == 8); 2770ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2771ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->Iex.Const.con->tag == Ico_F64) { 2772ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown u.f64 = e->Iex.Const.con->Ico.F64; 2773ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2774ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown else if (e->Iex.Const.con->tag == Ico_F64i) { 2775ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown u.u64 = e->Iex.Const.con->Ico.F64i; 2776ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2777ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown else 2778ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vpanic("iselDblExpr(amd64): const"); 2779ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2780ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_Imm64(u.u64, tmp)); 2781ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_Push(AMD64RMI_Reg(tmp))); 2782ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_SseLdSt( 2783ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown True/*load*/, 8, res, 2784ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown AMD64AMode_IR(0, hregAMD64_RSP()) 2785ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown )); 2786ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown add_to_rsp(env, 8); 2787ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 2788ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2789ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2790ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->tag == Iex_Load && e->Iex.Load.end == Iend_LE) { 2791ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown AMD64AMode* am; 2792ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegV(env); 2793ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert(e->Iex.Load.ty == Ity_F64); 2794ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown am = iselIntExpr_AMode(env, e->Iex.Load.addr); 2795ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_SseLdSt( True/*load*/, 8, res, am )); 2796ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 2797ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2798ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2799ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->tag == Iex_Get) { 2800ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown AMD64AMode* am = AMD64AMode_IR( e->Iex.Get.offset, 2801ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown hregAMD64_RBP() ); 2802ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegV(env); 2803ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_SseLdSt( True/*load*/, 8, res, am )); 2804ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 2805ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2806ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2807ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->tag == Iex_GetI) { 2808ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown AMD64AMode* am 2809ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown = genGuestArrayOffset( 2810ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown env, e->Iex.GetI.descr, 2811ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown e->Iex.GetI.ix, e->Iex.GetI.bias ); 2812ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegV(env); 2813ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_SseLdSt( True/*load*/, 8, res, am )); 2814ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 2815ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2816ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2817ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->tag == Iex_Triop) { 2818663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng IRTriop *triop = e->Iex.Triop.details; 2819ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown AMD64SseOp op = Asse_INVALID; 2820663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng switch (triop->op) { 2821ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_AddF64: op = Asse_ADDF; break; 2822ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_SubF64: op = Asse_SUBF; break; 2823ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_MulF64: op = Asse_MULF; break; 2824ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_DivF64: op = Asse_DIVF; break; 2825ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: break; 2826ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2827ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (op != Asse_INVALID) { 2828ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg dst = newVRegV(env); 2829663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng HReg argL = iselDblExpr(env, triop->arg2); 2830663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng HReg argR = iselDblExpr(env, triop->arg3); 2831ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, mk_vMOVsd_RR(argL, dst)); 2832ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* XXXROUNDINGFIXME */ 2833ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* set roundingmode here */ 2834ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_Sse64FLo(op, argR, dst)); 2835ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return dst; 2836ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2837ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2838ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2839436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov if (e->tag == Iex_Qop && e->Iex.Qop.details->op == Iop_MAddF64) { 2840436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov IRQop *qop = e->Iex.Qop.details; 2841436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov HReg dst = newVRegV(env); 2842436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov HReg argX = iselDblExpr(env, qop->arg2); 2843436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov HReg argY = iselDblExpr(env, qop->arg3); 2844436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov HReg argZ = iselDblExpr(env, qop->arg4); 2845436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /* XXXROUNDINGFIXME */ 2846436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /* set roundingmode here */ 2847436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /* subq $32, %rsp -- make a space*/ 2848436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov sub_from_rsp(env, 32); 2849436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /* Prepare 4 arg regs: 2850436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov leaq 0(%rsp), %rdi 2851436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov leaq 8(%rsp), %rsi 2852436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov leaq 16(%rsp), %rdx 2853436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov leaq 24(%rsp), %rcx 2854436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov */ 2855436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov addInstr(env, AMD64Instr_Lea64(AMD64AMode_IR(0, hregAMD64_RSP()), 2856436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov hregAMD64_RDI())); 2857436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov addInstr(env, AMD64Instr_Lea64(AMD64AMode_IR(8, hregAMD64_RSP()), 2858436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov hregAMD64_RSI())); 2859436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov addInstr(env, AMD64Instr_Lea64(AMD64AMode_IR(16, hregAMD64_RSP()), 2860436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov hregAMD64_RDX())); 2861436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov addInstr(env, AMD64Instr_Lea64(AMD64AMode_IR(24, hregAMD64_RSP()), 2862436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov hregAMD64_RCX())); 2863436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /* Store the three args, at (%rsi), (%rdx) and (%rcx): 2864436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov movsd %argX, 0(%rsi) 2865436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov movsd %argY, 0(%rdx) 2866436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov movsd %argZ, 0(%rcx) 2867436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov */ 2868436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov addInstr(env, AMD64Instr_SseLdSt(False/*!isLoad*/, 8, argX, 2869436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov AMD64AMode_IR(0, hregAMD64_RSI()))); 2870436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov addInstr(env, AMD64Instr_SseLdSt(False/*!isLoad*/, 8, argY, 2871436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov AMD64AMode_IR(0, hregAMD64_RDX()))); 2872436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov addInstr(env, AMD64Instr_SseLdSt(False/*!isLoad*/, 8, argZ, 2873436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov AMD64AMode_IR(0, hregAMD64_RCX()))); 2874436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /* call the helper */ 2875436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov addInstr(env, AMD64Instr_Call( Acc_ALWAYS, 2876436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov (ULong)(HWord)h_generic_calc_MAddF64, 2877436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 4, mk_RetLoc_simple(RLPri_None) )); 2878436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /* fetch the result from memory, using %r_argp, which the 2879436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov register allocator will keep alive across the call. */ 2880436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov addInstr(env, AMD64Instr_SseLdSt(True/*isLoad*/, 8, dst, 2881436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov AMD64AMode_IR(0, hregAMD64_RSP()))); 2882436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /* and finally, clear the space */ 2883436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov add_to_rsp(env, 32); 2884436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov return dst; 2885436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } 2886436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 2887ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->tag == Iex_Binop && e->Iex.Binop.op == Iop_RoundF64toInt) { 2888ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown AMD64AMode* m8_rsp = AMD64AMode_IR(-8, hregAMD64_RSP()); 2889ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg arg = iselDblExpr(env, e->Iex.Binop.arg2); 2890ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg dst = newVRegV(env); 2891ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2892ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* rf now holds the value to be rounded. The first thing to do 2893ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown is set the FPU's rounding mode accordingly. */ 2894ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2895ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Set host x87 rounding mode */ 2896ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown set_FPU_rounding_mode( env, e->Iex.Binop.arg1 ); 2897ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2898ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_SseLdSt(False/*store*/, 8, arg, m8_rsp)); 2899ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_A87Free(1)); 2900ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_A87PushPop(m8_rsp, True/*push*/, 8)); 2901ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_A87FpOp(Afp_ROUND)); 2902ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_A87PushPop(m8_rsp, False/*pop*/, 8)); 2903ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_SseLdSt(True/*load*/, 8, dst, m8_rsp)); 2904ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2905ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Restore default x87 rounding. */ 2906ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown set_FPU_rounding_default( env ); 2907ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2908ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return dst; 2909ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2910ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2911663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng IRTriop *triop = e->Iex.Triop.details; 2912ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->tag == Iex_Triop 2913663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng && (triop->op == Iop_ScaleF64 2914663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng || triop->op == Iop_AtanF64 2915663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng || triop->op == Iop_Yl2xF64 2916663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng || triop->op == Iop_Yl2xp1F64 2917663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng || triop->op == Iop_PRemF64 2918663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng || triop->op == Iop_PRem1F64) 2919ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ) { 2920ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown AMD64AMode* m8_rsp = AMD64AMode_IR(-8, hregAMD64_RSP()); 2921663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng HReg arg1 = iselDblExpr(env, triop->arg2); 2922663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng HReg arg2 = iselDblExpr(env, triop->arg3); 2923ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg dst = newVRegV(env); 2924663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng Bool arg2first = toBool(triop->op == Iop_ScaleF64 2925663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng || triop->op == Iop_PRemF64 2926663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng || triop->op == Iop_PRem1F64); 2927ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_A87Free(2)); 2928ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2929ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* one arg -> top of x87 stack */ 2930ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_SseLdSt( 2931ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown False/*store*/, 8, arg2first ? arg2 : arg1, m8_rsp)); 2932ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_A87PushPop(m8_rsp, True/*push*/, 8)); 2933ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2934ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* other arg -> top of x87 stack */ 2935ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_SseLdSt( 2936ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown False/*store*/, 8, arg2first ? arg1 : arg2, m8_rsp)); 2937ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_A87PushPop(m8_rsp, True/*push*/, 8)); 2938ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2939ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* do it */ 2940ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* XXXROUNDINGFIXME */ 2941ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* set roundingmode here */ 2942663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng switch (triop->op) { 2943ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_ScaleF64: 2944ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_A87FpOp(Afp_SCALE)); 2945ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 2946ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_AtanF64: 2947ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_A87FpOp(Afp_ATAN)); 2948ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 2949ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Yl2xF64: 2950ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_A87FpOp(Afp_YL2X)); 2951ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 2952ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Yl2xp1F64: 2953ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_A87FpOp(Afp_YL2XP1)); 2954ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 2955ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_PRemF64: 2956ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_A87FpOp(Afp_PREM)); 2957ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 2958ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_PRem1F64: 2959ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_A87FpOp(Afp_PREM1)); 2960ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 2961ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: 2962ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert(0); 2963ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2964ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2965ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* save result */ 2966ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_A87PushPop(m8_rsp, False/*pop*/, 8)); 2967ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_SseLdSt(True/*load*/, 8, dst, m8_rsp)); 2968ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return dst; 2969ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2970ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2971ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->tag == Iex_Binop && e->Iex.Binop.op == Iop_I64StoF64) { 2972ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg dst = newVRegV(env); 2973ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg src = iselIntExpr_R(env, e->Iex.Binop.arg2); 2974ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown set_SSE_rounding_mode( env, e->Iex.Binop.arg1 ); 2975ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_SseSI2SF( 8, 8, src, dst )); 2976ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown set_SSE_rounding_default( env ); 2977ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return dst; 2978ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2979ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2980ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->tag == Iex_Unop && e->Iex.Unop.op == Iop_I32StoF64) { 2981ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg dst = newVRegV(env); 2982ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg src = iselIntExpr_R(env, e->Iex.Unop.arg); 2983ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown set_SSE_rounding_default( env ); 2984ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_SseSI2SF( 4, 8, src, dst )); 2985ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return dst; 2986ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2987ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2988ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->tag == Iex_Unop 2989ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && (e->Iex.Unop.op == Iop_NegF64 2990ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown || e->Iex.Unop.op == Iop_AbsF64)) { 2991ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Sigh ... very rough code. Could do much better. */ 2992ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Get the 128-bit literal 00---0 10---0 into a register 2993ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown and xor/nand it with the value to be negated. */ 2994ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg r1 = newVRegI(env); 2995ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg dst = newVRegV(env); 2996ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg tmp = newVRegV(env); 2997ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg src = iselDblExpr(env, e->Iex.Unop.arg); 2998ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown AMD64AMode* rsp0 = AMD64AMode_IR(0, hregAMD64_RSP()); 2999ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, mk_vMOVsd_RR(src,tmp)); 3000ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_Push(AMD64RMI_Imm(0))); 3001ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_Imm64( 1ULL<<63, r1 )); 3002ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_Push(AMD64RMI_Reg(r1))); 3003ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_SseLdSt(True, 16, dst, rsp0)); 3004ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3005ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->Iex.Unop.op == Iop_NegF64) 3006ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_SseReRg(Asse_XOR, tmp, dst)); 3007ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown else 3008ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_SseReRg(Asse_ANDN, tmp, dst)); 3009ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3010ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown add_to_rsp(env, 16); 3011ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return dst; 3012ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3013ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3014ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->tag == Iex_Binop) { 3015ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown A87FpOp fpop = Afp_INVALID; 3016ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (e->Iex.Binop.op) { 3017ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_SqrtF64: fpop = Afp_SQRT; break; 3018ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_SinF64: fpop = Afp_SIN; break; 3019ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CosF64: fpop = Afp_COS; break; 3020ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_TanF64: fpop = Afp_TAN; break; 3021ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_2xm1F64: fpop = Afp_2XM1; break; 3022ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: break; 3023ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3024ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (fpop != Afp_INVALID) { 3025ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown AMD64AMode* m8_rsp = AMD64AMode_IR(-8, hregAMD64_RSP()); 3026ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg arg = iselDblExpr(env, e->Iex.Binop.arg2); 3027ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg dst = newVRegV(env); 3028ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int nNeeded = e->Iex.Binop.op==Iop_TanF64 ? 2 : 1; 3029ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_SseLdSt(False/*store*/, 8, arg, m8_rsp)); 3030ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_A87Free(nNeeded)); 3031ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_A87PushPop(m8_rsp, True/*push*/, 8)); 3032ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* XXXROUNDINGFIXME */ 3033ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* set roundingmode here */ 3034eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov /* Note that AMD64Instr_A87FpOp(Afp_TAN) sets the condition 3035eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov codes. I don't think that matters, since this insn 3036eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov selector never generates such an instruction intervening 3037eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov between an flag-setting instruction and a flag-using 3038eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov instruction. */ 3039ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_A87FpOp(fpop)); 3040ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_A87PushPop(m8_rsp, False/*pop*/, 8)); 3041ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_SseLdSt(True/*load*/, 8, dst, m8_rsp)); 3042ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return dst; 3043ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3044ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3045ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3046ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->tag == Iex_Unop) { 3047ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (e->Iex.Unop.op) { 3048ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//.. case Iop_I32toF64: { 3049ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//.. HReg dst = newVRegF(env); 3050ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//.. HReg ri = iselIntExpr_R(env, e->Iex.Unop.arg); 3051ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//.. addInstr(env, X86Instr_Push(X86RMI_Reg(ri))); 3052ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//.. set_FPU_rounding_default(env); 3053ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//.. addInstr(env, X86Instr_FpLdStI( 3054ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//.. True/*load*/, 4, dst, 3055ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//.. X86AMode_IR(0, hregX86_ESP()))); 3056ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//.. add_to_esp(env, 4); 3057ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//.. return dst; 3058ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//.. } 3059ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_ReinterpI64asF64: { 3060ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Given an I64, produce an IEEE754 double with the same 3061ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown bit pattern. */ 3062ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown AMD64AMode* m8_rsp = AMD64AMode_IR(-8, hregAMD64_RSP()); 3063ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg dst = newVRegV(env); 3064ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown AMD64RI* src = iselIntExpr_RI(env, e->Iex.Unop.arg); 3065ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* paranoia */ 3066ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown set_SSE_rounding_default(env); 3067ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_Alu64M(Aalu_MOV, src, m8_rsp)); 3068ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_SseLdSt(True/*load*/, 8, dst, m8_rsp)); 3069ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return dst; 3070ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3071ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_F32toF64: { 3072ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg f32; 3073ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg f64 = newVRegV(env); 3074ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* this shouldn't be necessary, but be paranoid ... */ 3075ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown set_SSE_rounding_default(env); 3076ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown f32 = iselFltExpr(env, e->Iex.Unop.arg); 3077ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_SseSDSS(False/*S->D*/, f32, f64)); 3078ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return f64; 3079ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3080ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: 3081ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 3082ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3083ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3084ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3085ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* --------- MULTIPLEX --------- */ 3086436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov if (e->tag == Iex_ITE) { // VFD 3087436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov HReg r1, r0, dst; 3088ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert(ty == Ity_F64); 3089436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov vassert(typeOfIRExpr(env->type_env,e->Iex.ITE.cond) == Ity_I1); 3090436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov r1 = iselDblExpr(env, e->Iex.ITE.iftrue); 3091436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov r0 = iselDblExpr(env, e->Iex.ITE.iffalse); 3092ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown dst = newVRegV(env); 3093436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov addInstr(env, mk_vMOVsd_RR(r1,dst)); 3094436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov AMD64CondCode cc = iselCondCode(env, e->Iex.ITE.cond); 3095436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov addInstr(env, AMD64Instr_SseCMov(cc ^ 1, r0, dst)); 3096ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return dst; 3097ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3098ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3099ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ppIRExpr(e); 3100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vpanic("iselDblExpr_wrk"); 3101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 3102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------*/ 3105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- ISEL: SIMD (Vector) expressions, 128 bit. ---*/ 3106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------*/ 3107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic HReg iselVecExpr ( ISelEnv* env, IRExpr* e ) 3109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 3110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg r = iselVecExpr_wrk( env, e ); 3111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# if 0 3112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vex_printf("\n"); ppIRExpr(e); vex_printf("\n"); 3113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 3114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert(hregClass(r) == HRcVec128); 3115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert(hregIsVirtual(r)); 3116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return r; 3117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 3118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* DO NOT CALL THIS DIRECTLY */ 3121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic HReg iselVecExpr_wrk ( ISelEnv* env, IRExpr* e ) 3122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 3123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HWord fn = 0; /* address of helper fn, if required */ 3124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bool arg1isEReg = False; 3125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown AMD64SseOp op = Asse_INVALID; 3126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRType ty = typeOfIRExpr(env->type_env,e); 3127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert(e); 3128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert(ty == Ity_V128); 3129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->tag == Iex_RdTmp) { 3131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return lookupIRTemp(env, e->Iex.RdTmp.tmp); 3132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->tag == Iex_Get) { 3135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg dst = newVRegV(env); 3136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_SseLdSt( 3137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown True/*load*/, 3138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 16, 3139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown dst, 3140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown AMD64AMode_IR(e->Iex.Get.offset, hregAMD64_RBP()) 3141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ) 3142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ); 3143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return dst; 3144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->tag == Iex_Load && e->Iex.Load.end == Iend_LE) { 3147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg dst = newVRegV(env); 3148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown AMD64AMode* am = iselIntExpr_AMode(env, e->Iex.Load.addr); 3149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_SseLdSt( True/*load*/, 16, dst, am )); 3150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return dst; 3151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->tag == Iex_Const) { 3154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg dst = newVRegV(env); 3155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert(e->Iex.Const.con->tag == Ico_V128); 3156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (e->Iex.Const.con->Ico.V128) { 3157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case 0x0000: 3158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown dst = generate_zeroes_V128(env); 3159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 3160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case 0xFFFF: 3161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown dst = generate_ones_V128(env); 3162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 3163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: { 3164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown AMD64AMode* rsp0 = AMD64AMode_IR(0, hregAMD64_RSP()); 3165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* do push_uimm64 twice, first time for the high-order half. */ 3166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown push_uimm64(env, bitmask8_to_bytemask64( 3167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (e->Iex.Const.con->Ico.V128 >> 8) & 0xFF 3168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown )); 3169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown push_uimm64(env, bitmask8_to_bytemask64( 3170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (e->Iex.Const.con->Ico.V128 >> 0) & 0xFF 3171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown )); 3172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_SseLdSt( True/*load*/, 16, dst, rsp0 )); 3173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown add_to_rsp(env, 16); 3174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 3175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return dst; 3178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->tag == Iex_Unop) { 3181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (e->Iex.Unop.op) { 3182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_NotV128: { 3184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg arg = iselVecExpr(env, e->Iex.Unop.arg); 3185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return do_sse_NotV128(env, arg); 3186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CmpNEZ64x2: { 3189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* We can use SSE2 instructions for this. */ 3190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Ideally, we want to do a 64Ix2 comparison against zero of 3191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown the operand. Problem is no such insn exists. Solution 3192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown therefore is to do a 32Ix4 comparison instead, and bitwise- 3193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown negate (NOT) the result. Let a,b,c,d be 32-bit lanes, and 3194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown let the not'd result of this initial comparison be a:b:c:d. 3195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown What we need to compute is (a|b):(a|b):(c|d):(c|d). So, use 3196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pshufd to create a value b:a:d:c, and OR that with a:b:c:d, 3197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown giving the required result. 3198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown The required selection sequence is 2,3,0,1, which 3200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown according to Intel's documentation means the pshufd 3201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown literal value is 0xB1, that is, 3202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (2 << 6) | (3 << 4) | (0 << 2) | (1 << 0) 3203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */ 3204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg arg = iselVecExpr(env, e->Iex.Unop.arg); 3205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg tmp = generate_zeroes_V128(env); 3206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg dst = newVRegV(env); 3207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_SseReRg(Asse_CMPEQ32, arg, tmp)); 3208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tmp = do_sse_NotV128(env, tmp); 3209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_SseShuf(0xB1, tmp, dst)); 3210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_SseReRg(Asse_OR, tmp, dst)); 3211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return dst; 3212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CmpNEZ32x4: op = Asse_CMPEQ32; goto do_CmpNEZ_vector; 3215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CmpNEZ16x8: op = Asse_CMPEQ16; goto do_CmpNEZ_vector; 3216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CmpNEZ8x16: op = Asse_CMPEQ8; goto do_CmpNEZ_vector; 3217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown do_CmpNEZ_vector: 3218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown { 3219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg arg = iselVecExpr(env, e->Iex.Unop.arg); 3220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg tmp = newVRegV(env); 3221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg zero = generate_zeroes_V128(env); 3222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg dst; 3223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, mk_vMOVsd_RR(arg, tmp)); 3224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_SseReRg(op, zero, tmp)); 3225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown dst = do_sse_NotV128(env, tmp); 3226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return dst; 3227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Recip32Fx4: op = Asse_RCPF; goto do_32Fx4_unary; 3230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_RSqrt32Fx4: op = Asse_RSQRTF; goto do_32Fx4_unary; 3231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Sqrt32Fx4: op = Asse_SQRTF; goto do_32Fx4_unary; 3232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown do_32Fx4_unary: 3233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown { 3234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg arg = iselVecExpr(env, e->Iex.Unop.arg); 3235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg dst = newVRegV(env); 3236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_Sse32Fx4(op, arg, dst)); 3237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return dst; 3238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Sqrt64Fx2: op = Asse_SQRTF; goto do_64Fx2_unary; 3241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown do_64Fx2_unary: 3242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown { 3243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg arg = iselVecExpr(env, e->Iex.Unop.arg); 3244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg dst = newVRegV(env); 3245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_Sse64Fx2(op, arg, dst)); 3246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return dst; 3247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Recip32F0x4: op = Asse_RCPF; goto do_32F0x4_unary; 3250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_RSqrt32F0x4: op = Asse_RSQRTF; goto do_32F0x4_unary; 3251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Sqrt32F0x4: op = Asse_SQRTF; goto do_32F0x4_unary; 3252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown do_32F0x4_unary: 3253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown { 3254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* A bit subtle. We have to copy the arg to the result 3255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown register first, because actually doing the SSE scalar insn 3256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown leaves the upper 3/4 of the destination register 3257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown unchanged. Whereas the required semantics of these 3258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown primops is that the upper 3/4 is simply copied in from the 3259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown argument. */ 3260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg arg = iselVecExpr(env, e->Iex.Unop.arg); 3261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg dst = newVRegV(env); 3262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, mk_vMOVsd_RR(arg, dst)); 3263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_Sse32FLo(op, arg, dst)); 3264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return dst; 3265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Sqrt64F0x2: op = Asse_SQRTF; goto do_64F0x2_unary; 3268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown do_64F0x2_unary: 3269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown { 3270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* A bit subtle. We have to copy the arg to the result 3271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown register first, because actually doing the SSE scalar insn 3272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown leaves the upper half of the destination register 3273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown unchanged. Whereas the required semantics of these 3274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown primops is that the upper half is simply copied in from the 3275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown argument. */ 3276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg arg = iselVecExpr(env, e->Iex.Unop.arg); 3277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg dst = newVRegV(env); 3278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, mk_vMOVsd_RR(arg, dst)); 3279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_Sse64FLo(op, arg, dst)); 3280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return dst; 3281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_32UtoV128: { 3284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg dst = newVRegV(env); 3285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown AMD64AMode* rsp_m32 = AMD64AMode_IR(-32, hregAMD64_RSP()); 3286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown AMD64RI* ri = iselIntExpr_RI(env, e->Iex.Unop.arg); 3287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_Alu64M(Aalu_MOV, ri, rsp_m32)); 3288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_SseLdzLO(4, dst, rsp_m32)); 3289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return dst; 3290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_64UtoV128: { 3293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg dst = newVRegV(env); 3294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown AMD64AMode* rsp0 = AMD64AMode_IR(0, hregAMD64_RSP()); 3295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown AMD64RMI* rmi = iselIntExpr_RMI(env, e->Iex.Unop.arg); 3296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_Push(rmi)); 3297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_SseLdzLO(8, dst, rsp0)); 3298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown add_to_rsp(env, 8); 3299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return dst; 3300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3302663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng case Iop_V256toV128_0: 3303663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng case Iop_V256toV128_1: { 3304663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng HReg vHi, vLo; 3305663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng iselDVecExpr(&vHi, &vLo, env, e->Iex.Unop.arg); 3306663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng return (e->Iex.Unop.op == Iop_V256toV128_1) ? vHi : vLo; 3307663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng } 3308663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 3309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: 3310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 3311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } /* switch (e->Iex.Unop.op) */ 3312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } /* if (e->tag == Iex_Unop) */ 3313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->tag == Iex_Binop) { 3315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (e->Iex.Binop.op) { 3316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3317663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng /* FIXME: could we generate MOVQ here? */ 3318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_SetV128lo64: { 3319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg dst = newVRegV(env); 3320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg srcV = iselVecExpr(env, e->Iex.Binop.arg1); 3321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg srcI = iselIntExpr_R(env, e->Iex.Binop.arg2); 3322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown AMD64AMode* rsp_m16 = AMD64AMode_IR(-16, hregAMD64_RSP()); 3323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_SseLdSt(False/*store*/, 16, srcV, rsp_m16)); 3324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_Alu64M(Aalu_MOV, AMD64RI_Reg(srcI), rsp_m16)); 3325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_SseLdSt(True/*load*/, 16, dst, rsp_m16)); 3326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return dst; 3327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3329663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng /* FIXME: could we generate MOVD here? */ 3330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_SetV128lo32: { 3331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg dst = newVRegV(env); 3332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg srcV = iselVecExpr(env, e->Iex.Binop.arg1); 3333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg srcI = iselIntExpr_R(env, e->Iex.Binop.arg2); 3334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown AMD64AMode* rsp_m16 = AMD64AMode_IR(-16, hregAMD64_RSP()); 3335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_SseLdSt(False/*store*/, 16, srcV, rsp_m16)); 3336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_Store(4, srcI, rsp_m16)); 3337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_SseLdSt(True/*load*/, 16, dst, rsp_m16)); 3338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return dst; 3339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_64HLtoV128: { 3342663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng HReg rsp = hregAMD64_RSP(); 3343663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng AMD64AMode* m8_rsp = AMD64AMode_IR(-8, rsp); 3344663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng AMD64AMode* m16_rsp = AMD64AMode_IR(-16, rsp); 3345663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng AMD64RI* qHi = iselIntExpr_RI(env, e->Iex.Binop.arg1); 3346663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng AMD64RI* qLo = iselIntExpr_RI(env, e->Iex.Binop.arg2); 3347663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng addInstr(env, AMD64Instr_Alu64M(Aalu_MOV, qHi, m8_rsp)); 3348663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng addInstr(env, AMD64Instr_Alu64M(Aalu_MOV, qLo, m16_rsp)); 3349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg dst = newVRegV(env); 3350663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng /* One store-forwarding stall coming up, oh well :-( */ 3351663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng addInstr(env, AMD64Instr_SseLdSt(True/*load*/, 16, dst, m16_rsp)); 3352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return dst; 3353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CmpEQ32Fx4: op = Asse_CMPEQF; goto do_32Fx4; 3356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CmpLT32Fx4: op = Asse_CMPLTF; goto do_32Fx4; 3357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CmpLE32Fx4: op = Asse_CMPLEF; goto do_32Fx4; 3358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CmpUN32Fx4: op = Asse_CMPUNF; goto do_32Fx4; 3359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Max32Fx4: op = Asse_MAXF; goto do_32Fx4; 3360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Min32Fx4: op = Asse_MINF; goto do_32Fx4; 3361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown do_32Fx4: 3362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown { 3363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselVecExpr(env, e->Iex.Binop.arg1); 3364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselVecExpr(env, e->Iex.Binop.arg2); 3365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg dst = newVRegV(env); 3366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, mk_vMOVsd_RR(argL, dst)); 3367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_Sse32Fx4(op, argR, dst)); 3368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return dst; 3369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CmpEQ64Fx2: op = Asse_CMPEQF; goto do_64Fx2; 3372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CmpLT64Fx2: op = Asse_CMPLTF; goto do_64Fx2; 3373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CmpLE64Fx2: op = Asse_CMPLEF; goto do_64Fx2; 3374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CmpUN64Fx2: op = Asse_CMPUNF; goto do_64Fx2; 3375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Max64Fx2: op = Asse_MAXF; goto do_64Fx2; 3376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Min64Fx2: op = Asse_MINF; goto do_64Fx2; 3377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown do_64Fx2: 3378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown { 3379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselVecExpr(env, e->Iex.Binop.arg1); 3380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselVecExpr(env, e->Iex.Binop.arg2); 3381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg dst = newVRegV(env); 3382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, mk_vMOVsd_RR(argL, dst)); 3383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_Sse64Fx2(op, argR, dst)); 3384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return dst; 3385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CmpEQ32F0x4: op = Asse_CMPEQF; goto do_32F0x4; 3388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CmpLT32F0x4: op = Asse_CMPLTF; goto do_32F0x4; 3389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CmpLE32F0x4: op = Asse_CMPLEF; goto do_32F0x4; 3390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CmpUN32F0x4: op = Asse_CMPUNF; goto do_32F0x4; 3391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Add32F0x4: op = Asse_ADDF; goto do_32F0x4; 3392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Div32F0x4: op = Asse_DIVF; goto do_32F0x4; 3393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Max32F0x4: op = Asse_MAXF; goto do_32F0x4; 3394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Min32F0x4: op = Asse_MINF; goto do_32F0x4; 3395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Mul32F0x4: op = Asse_MULF; goto do_32F0x4; 3396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Sub32F0x4: op = Asse_SUBF; goto do_32F0x4; 3397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown do_32F0x4: { 3398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselVecExpr(env, e->Iex.Binop.arg1); 3399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselVecExpr(env, e->Iex.Binop.arg2); 3400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg dst = newVRegV(env); 3401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, mk_vMOVsd_RR(argL, dst)); 3402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_Sse32FLo(op, argR, dst)); 3403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return dst; 3404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CmpEQ64F0x2: op = Asse_CMPEQF; goto do_64F0x2; 3407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CmpLT64F0x2: op = Asse_CMPLTF; goto do_64F0x2; 3408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CmpLE64F0x2: op = Asse_CMPLEF; goto do_64F0x2; 3409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CmpUN64F0x2: op = Asse_CMPUNF; goto do_64F0x2; 3410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Add64F0x2: op = Asse_ADDF; goto do_64F0x2; 3411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Div64F0x2: op = Asse_DIVF; goto do_64F0x2; 3412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Max64F0x2: op = Asse_MAXF; goto do_64F0x2; 3413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Min64F0x2: op = Asse_MINF; goto do_64F0x2; 3414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Mul64F0x2: op = Asse_MULF; goto do_64F0x2; 3415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Sub64F0x2: op = Asse_SUBF; goto do_64F0x2; 3416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown do_64F0x2: { 3417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselVecExpr(env, e->Iex.Binop.arg1); 3418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselVecExpr(env, e->Iex.Binop.arg2); 3419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg dst = newVRegV(env); 3420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, mk_vMOVsd_RR(argL, dst)); 3421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_Sse64FLo(op, argR, dst)); 3422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return dst; 3423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3425b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov case Iop_QNarrowBin32Sto16Sx8: 3426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown op = Asse_PACKSSD; arg1isEReg = True; goto do_SseReRg; 3427b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov case Iop_QNarrowBin16Sto8Sx16: 3428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown op = Asse_PACKSSW; arg1isEReg = True; goto do_SseReRg; 3429b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov case Iop_QNarrowBin16Sto8Ux16: 3430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown op = Asse_PACKUSW; arg1isEReg = True; goto do_SseReRg; 3431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_InterleaveHI8x16: 3433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown op = Asse_UNPCKHB; arg1isEReg = True; goto do_SseReRg; 3434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_InterleaveHI16x8: 3435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown op = Asse_UNPCKHW; arg1isEReg = True; goto do_SseReRg; 3436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_InterleaveHI32x4: 3437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown op = Asse_UNPCKHD; arg1isEReg = True; goto do_SseReRg; 3438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_InterleaveHI64x2: 3439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown op = Asse_UNPCKHQ; arg1isEReg = True; goto do_SseReRg; 3440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_InterleaveLO8x16: 3442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown op = Asse_UNPCKLB; arg1isEReg = True; goto do_SseReRg; 3443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_InterleaveLO16x8: 3444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown op = Asse_UNPCKLW; arg1isEReg = True; goto do_SseReRg; 3445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_InterleaveLO32x4: 3446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown op = Asse_UNPCKLD; arg1isEReg = True; goto do_SseReRg; 3447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_InterleaveLO64x2: 3448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown op = Asse_UNPCKLQ; arg1isEReg = True; goto do_SseReRg; 3449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_AndV128: op = Asse_AND; goto do_SseReRg; 3451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_OrV128: op = Asse_OR; goto do_SseReRg; 3452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_XorV128: op = Asse_XOR; goto do_SseReRg; 3453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Add8x16: op = Asse_ADD8; goto do_SseReRg; 3454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Add16x8: op = Asse_ADD16; goto do_SseReRg; 3455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Add32x4: op = Asse_ADD32; goto do_SseReRg; 3456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Add64x2: op = Asse_ADD64; goto do_SseReRg; 3457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QAdd8Sx16: op = Asse_QADD8S; goto do_SseReRg; 3458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QAdd16Sx8: op = Asse_QADD16S; goto do_SseReRg; 3459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QAdd8Ux16: op = Asse_QADD8U; goto do_SseReRg; 3460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QAdd16Ux8: op = Asse_QADD16U; goto do_SseReRg; 3461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Avg8Ux16: op = Asse_AVG8U; goto do_SseReRg; 3462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Avg16Ux8: op = Asse_AVG16U; goto do_SseReRg; 3463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CmpEQ8x16: op = Asse_CMPEQ8; goto do_SseReRg; 3464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CmpEQ16x8: op = Asse_CMPEQ16; goto do_SseReRg; 3465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CmpEQ32x4: op = Asse_CMPEQ32; goto do_SseReRg; 3466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CmpGT8Sx16: op = Asse_CMPGT8S; goto do_SseReRg; 3467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CmpGT16Sx8: op = Asse_CMPGT16S; goto do_SseReRg; 3468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CmpGT32Sx4: op = Asse_CMPGT32S; goto do_SseReRg; 3469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Max16Sx8: op = Asse_MAX16S; goto do_SseReRg; 3470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Max8Ux16: op = Asse_MAX8U; goto do_SseReRg; 3471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Min16Sx8: op = Asse_MIN16S; goto do_SseReRg; 3472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Min8Ux16: op = Asse_MIN8U; goto do_SseReRg; 3473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_MulHi16Ux8: op = Asse_MULHI16U; goto do_SseReRg; 3474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_MulHi16Sx8: op = Asse_MULHI16S; goto do_SseReRg; 3475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Mul16x8: op = Asse_MUL16; goto do_SseReRg; 3476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Sub8x16: op = Asse_SUB8; goto do_SseReRg; 3477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Sub16x8: op = Asse_SUB16; goto do_SseReRg; 3478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Sub32x4: op = Asse_SUB32; goto do_SseReRg; 3479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Sub64x2: op = Asse_SUB64; goto do_SseReRg; 3480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QSub8Sx16: op = Asse_QSUB8S; goto do_SseReRg; 3481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QSub16Sx8: op = Asse_QSUB16S; goto do_SseReRg; 3482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QSub8Ux16: op = Asse_QSUB8U; goto do_SseReRg; 3483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QSub16Ux8: op = Asse_QSUB16U; goto do_SseReRg; 3484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown do_SseReRg: { 3485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg arg1 = iselVecExpr(env, e->Iex.Binop.arg1); 3486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg arg2 = iselVecExpr(env, e->Iex.Binop.arg2); 3487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg dst = newVRegV(env); 3488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (arg1isEReg) { 3489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, mk_vMOVsd_RR(arg2, dst)); 3490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_SseReRg(op, arg1, dst)); 3491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 3492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, mk_vMOVsd_RR(arg1, dst)); 3493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_SseReRg(op, arg2, dst)); 3494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return dst; 3496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_ShlN16x8: op = Asse_SHL16; goto do_SseShift; 3499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_ShlN32x4: op = Asse_SHL32; goto do_SseShift; 3500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_ShlN64x2: op = Asse_SHL64; goto do_SseShift; 3501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_SarN16x8: op = Asse_SAR16; goto do_SseShift; 3502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_SarN32x4: op = Asse_SAR32; goto do_SseShift; 3503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_ShrN16x8: op = Asse_SHR16; goto do_SseShift; 3504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_ShrN32x4: op = Asse_SHR32; goto do_SseShift; 3505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_ShrN64x2: op = Asse_SHR64; goto do_SseShift; 3506ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown do_SseShift: { 3507ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg greg = iselVecExpr(env, e->Iex.Binop.arg1); 3508ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown AMD64RMI* rmi = iselIntExpr_RMI(env, e->Iex.Binop.arg2); 3509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown AMD64AMode* rsp0 = AMD64AMode_IR(0, hregAMD64_RSP()); 3510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg ereg = newVRegV(env); 3511ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg dst = newVRegV(env); 3512ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_Push(AMD64RMI_Imm(0))); 3513ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_Push(rmi)); 3514ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_SseLdSt(True/*load*/, 16, ereg, rsp0)); 3515ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, mk_vMOVsd_RR(greg, dst)); 3516ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_SseReRg(op, ereg, dst)); 3517ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown add_to_rsp(env, 16); 3518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return dst; 3519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3521ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Mul32x4: fn = (HWord)h_generic_calc_Mul32x4; 3522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown goto do_SseAssistedBinary; 3523ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Max32Sx4: fn = (HWord)h_generic_calc_Max32Sx4; 3524ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown goto do_SseAssistedBinary; 3525ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Min32Sx4: fn = (HWord)h_generic_calc_Min32Sx4; 3526ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown goto do_SseAssistedBinary; 3527ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Max32Ux4: fn = (HWord)h_generic_calc_Max32Ux4; 3528ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown goto do_SseAssistedBinary; 3529ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Min32Ux4: fn = (HWord)h_generic_calc_Min32Ux4; 3530ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown goto do_SseAssistedBinary; 3531ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Max16Ux8: fn = (HWord)h_generic_calc_Max16Ux8; 3532ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown goto do_SseAssistedBinary; 3533ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Min16Ux8: fn = (HWord)h_generic_calc_Min16Ux8; 3534ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown goto do_SseAssistedBinary; 3535ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Max8Sx16: fn = (HWord)h_generic_calc_Max8Sx16; 3536ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown goto do_SseAssistedBinary; 3537ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Min8Sx16: fn = (HWord)h_generic_calc_Min8Sx16; 3538ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown goto do_SseAssistedBinary; 3539b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov case Iop_CmpEQ64x2: fn = (HWord)h_generic_calc_CmpEQ64x2; 3540b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov goto do_SseAssistedBinary; 3541ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CmpGT64Sx2: fn = (HWord)h_generic_calc_CmpGT64Sx2; 3542ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown goto do_SseAssistedBinary; 3543663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng case Iop_Perm32x4: fn = (HWord)h_generic_calc_Perm32x4; 3544663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng goto do_SseAssistedBinary; 3545b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov case Iop_QNarrowBin32Sto16Ux8: 3546b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov fn = (HWord)h_generic_calc_QNarrowBin32Sto16Ux8; 3547b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov goto do_SseAssistedBinary; 3548b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov case Iop_NarrowBin16to8x16: 3549b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov fn = (HWord)h_generic_calc_NarrowBin16to8x16; 3550b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov goto do_SseAssistedBinary; 3551b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov case Iop_NarrowBin32to16x8: 3552b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov fn = (HWord)h_generic_calc_NarrowBin32to16x8; 3553b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov goto do_SseAssistedBinary; 3554ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown do_SseAssistedBinary: { 3555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* RRRufff! RRRufff code is what we're generating here. Oh 3556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown well. */ 3557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert(fn != 0); 3558ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg dst = newVRegV(env); 3559ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselVecExpr(env, e->Iex.Binop.arg1); 3560ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselVecExpr(env, e->Iex.Binop.arg2); 3561ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argp = newVRegI(env); 3562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* subq $112, %rsp -- make a space*/ 3563ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sub_from_rsp(env, 112); 3564ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* leaq 48(%rsp), %r_argp -- point into it */ 3565ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_Lea64(AMD64AMode_IR(48, hregAMD64_RSP()), 3566ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown argp)); 3567ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* andq $-16, %r_argp -- 16-align the pointer */ 3568ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_Alu64R(Aalu_AND, 3569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown AMD64RMI_Imm( ~(UInt)15 ), 3570ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown argp)); 3571ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Prepare 3 arg regs: 3572ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown leaq 0(%r_argp), %rdi 3573ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown leaq 16(%r_argp), %rsi 3574ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown leaq 32(%r_argp), %rdx 3575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */ 3576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_Lea64(AMD64AMode_IR(0, argp), 3577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown hregAMD64_RDI())); 3578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_Lea64(AMD64AMode_IR(16, argp), 3579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown hregAMD64_RSI())); 3580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_Lea64(AMD64AMode_IR(32, argp), 3581ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown hregAMD64_RDX())); 3582ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Store the two args, at (%rsi) and (%rdx): 3583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown movupd %argL, 0(%rsi) 3584ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown movupd %argR, 0(%rdx) 3585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */ 3586ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_SseLdSt(False/*!isLoad*/, 16, argL, 3587ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown AMD64AMode_IR(0, hregAMD64_RSI()))); 3588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_SseLdSt(False/*!isLoad*/, 16, argR, 3589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown AMD64AMode_IR(0, hregAMD64_RDX()))); 3590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* call the helper */ 3591436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov addInstr(env, AMD64Instr_Call( Acc_ALWAYS, (ULong)fn, 3592436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 3, mk_RetLoc_simple(RLPri_None) )); 3593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* fetch the result from memory, using %r_argp, which the 3594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown register allocator will keep alive across the call. */ 3595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_SseLdSt(True/*isLoad*/, 16, dst, 3596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown AMD64AMode_IR(0, argp))); 3597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* and finally, clear the space */ 3598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown add_to_rsp(env, 112); 3599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return dst; 3600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3602f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root case Iop_SarN64x2: fn = (HWord)h_generic_calc_SarN64x2; 3603f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root goto do_SseAssistedVectorAndScalar; 3604f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root case Iop_SarN8x16: fn = (HWord)h_generic_calc_SarN8x16; 3605f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root goto do_SseAssistedVectorAndScalar; 3606f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root do_SseAssistedVectorAndScalar: { 3607f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root /* RRRufff! RRRufff code is what we're generating here. Oh 3608f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root well. */ 3609f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root vassert(fn != 0); 3610f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root HReg dst = newVRegV(env); 3611f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root HReg argL = iselVecExpr(env, e->Iex.Binop.arg1); 3612f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root HReg argR = iselIntExpr_R(env, e->Iex.Binop.arg2); 3613f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root HReg argp = newVRegI(env); 3614f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root /* subq $112, %rsp -- make a space*/ 3615f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root sub_from_rsp(env, 112); 3616f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root /* leaq 48(%rsp), %r_argp -- point into it */ 3617f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root addInstr(env, AMD64Instr_Lea64(AMD64AMode_IR(48, hregAMD64_RSP()), 3618f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root argp)); 3619f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root /* andq $-16, %r_argp -- 16-align the pointer */ 3620f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root addInstr(env, AMD64Instr_Alu64R(Aalu_AND, 3621f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root AMD64RMI_Imm( ~(UInt)15 ), 3622f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root argp)); 3623f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root /* Prepare 2 vector arg regs: 3624f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root leaq 0(%r_argp), %rdi 3625f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root leaq 16(%r_argp), %rsi 3626f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root */ 3627f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root addInstr(env, AMD64Instr_Lea64(AMD64AMode_IR(0, argp), 3628f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root hregAMD64_RDI())); 3629f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root addInstr(env, AMD64Instr_Lea64(AMD64AMode_IR(16, argp), 3630f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root hregAMD64_RSI())); 3631f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root /* Store the vector arg, at (%rsi): 3632f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root movupd %argL, 0(%rsi) 3633f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root */ 3634f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root addInstr(env, AMD64Instr_SseLdSt(False/*!isLoad*/, 16, argL, 3635f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root AMD64AMode_IR(0, hregAMD64_RSI()))); 3636f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root /* And get the scalar value into rdx */ 3637f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root addInstr(env, mk_iMOVsd_RR(argR, hregAMD64_RDX())); 3638f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root 3639f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root /* call the helper */ 3640436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov addInstr(env, AMD64Instr_Call( Acc_ALWAYS, (ULong)fn, 3641436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 3, mk_RetLoc_simple(RLPri_None) )); 3642f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root /* fetch the result from memory, using %r_argp, which the 3643f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root register allocator will keep alive across the call. */ 3644f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root addInstr(env, AMD64Instr_SseLdSt(True/*isLoad*/, 16, dst, 3645f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root AMD64AMode_IR(0, argp))); 3646f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root /* and finally, clear the space */ 3647f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root add_to_rsp(env, 112); 3648f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root return dst; 3649f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root } 3650f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root 3651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: 3652ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 3653ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } /* switch (e->Iex.Binop.op) */ 3654ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } /* if (e->tag == Iex_Binop) */ 3655ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3656436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov if (e->tag == Iex_Triop) { 3657436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov IRTriop *triop = e->Iex.Triop.details; 3658436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov switch (triop->op) { 3659436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 3660436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case Iop_Add64Fx2: op = Asse_ADDF; goto do_64Fx2_w_rm; 3661436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case Iop_Sub64Fx2: op = Asse_SUBF; goto do_64Fx2_w_rm; 3662436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case Iop_Mul64Fx2: op = Asse_MULF; goto do_64Fx2_w_rm; 3663436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case Iop_Div64Fx2: op = Asse_DIVF; goto do_64Fx2_w_rm; 3664436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov do_64Fx2_w_rm: 3665436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov { 3666436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov HReg argL = iselVecExpr(env, triop->arg2); 3667436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov HReg argR = iselVecExpr(env, triop->arg3); 3668436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov HReg dst = newVRegV(env); 3669436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov addInstr(env, mk_vMOVsd_RR(argL, dst)); 3670436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /* XXXROUNDINGFIXME */ 3671436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /* set roundingmode here */ 3672436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov addInstr(env, AMD64Instr_Sse64Fx2(op, argR, dst)); 3673436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov return dst; 3674436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } 3675436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 3676436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case Iop_Add32Fx4: op = Asse_ADDF; goto do_32Fx4_w_rm; 3677436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case Iop_Sub32Fx4: op = Asse_SUBF; goto do_32Fx4_w_rm; 3678436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case Iop_Mul32Fx4: op = Asse_MULF; goto do_32Fx4_w_rm; 3679436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case Iop_Div32Fx4: op = Asse_DIVF; goto do_32Fx4_w_rm; 3680436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov do_32Fx4_w_rm: 3681436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov { 3682436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov HReg argL = iselVecExpr(env, triop->arg2); 3683436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov HReg argR = iselVecExpr(env, triop->arg3); 3684436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov HReg dst = newVRegV(env); 3685436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov addInstr(env, mk_vMOVsd_RR(argL, dst)); 3686436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /* XXXROUNDINGFIXME */ 3687436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /* set roundingmode here */ 3688436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov addInstr(env, AMD64Instr_Sse32Fx4(op, argR, dst)); 3689436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov return dst; 3690436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } 3691436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 3692436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov default: 3693436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov break; 3694436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } /* switch (triop->op) */ 3695436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } /* if (e->tag == Iex_Triop) */ 3696436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 3697436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov if (e->tag == Iex_ITE) { // VFD 3698436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov HReg r1 = iselVecExpr(env, e->Iex.ITE.iftrue); 3699436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov HReg r0 = iselVecExpr(env, e->Iex.ITE.iffalse); 3700ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg dst = newVRegV(env); 3701436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov addInstr(env, mk_vMOVsd_RR(r1,dst)); 3702436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov AMD64CondCode cc = iselCondCode(env, e->Iex.ITE.cond); 3703436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov addInstr(env, AMD64Instr_SseCMov(cc ^ 1, r0, dst)); 3704ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return dst; 3705ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3706ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3707ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown //vec_fail: 3708ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vex_printf("iselVecExpr (amd64, subarch = %s): can't reduce\n", 3709ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown LibVEX_ppVexHwCaps(VexArchAMD64, env->hwcaps)); 3710ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ppIRExpr(e); 3711ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vpanic("iselVecExpr_wrk"); 3712ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 3713ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3714ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3715ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------*/ 3716663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/*--- ISEL: SIMD (V256) expressions, into 2 XMM regs. --*/ 3717663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/*---------------------------------------------------------*/ 3718663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 3719663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic void iselDVecExpr ( /*OUT*/HReg* rHi, /*OUT*/HReg* rLo, 3720663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng ISelEnv* env, IRExpr* e ) 3721663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{ 3722663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng iselDVecExpr_wrk( rHi, rLo, env, e ); 3723663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng# if 0 3724663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng vex_printf("\n"); ppIRExpr(e); vex_printf("\n"); 3725663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng# endif 3726663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng vassert(hregClass(*rHi) == HRcVec128); 3727663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng vassert(hregClass(*rLo) == HRcVec128); 3728663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng vassert(hregIsVirtual(*rHi)); 3729663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng vassert(hregIsVirtual(*rLo)); 3730663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng} 3731663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 3732663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 3733663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* DO NOT CALL THIS DIRECTLY */ 3734663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic void iselDVecExpr_wrk ( /*OUT*/HReg* rHi, /*OUT*/HReg* rLo, 3735663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng ISelEnv* env, IRExpr* e ) 3736663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{ 3737436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov HWord fn = 0; /* address of helper fn, if required */ 3738663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng vassert(e); 3739663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng IRType ty = typeOfIRExpr(env->type_env,e); 3740663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng vassert(ty == Ity_V256); 3741663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 3742663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng AMD64SseOp op = Asse_INVALID; 3743663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 3744663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng /* read 256-bit IRTemp */ 3745663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng if (e->tag == Iex_RdTmp) { 3746663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng lookupIRTempPair( rHi, rLo, env, e->Iex.RdTmp.tmp); 3747663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng return; 3748663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng } 3749663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 3750663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng if (e->tag == Iex_Get) { 3751663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng HReg vHi = newVRegV(env); 3752663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng HReg vLo = newVRegV(env); 3753663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng HReg rbp = hregAMD64_RBP(); 3754663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng AMD64AMode* am0 = AMD64AMode_IR(e->Iex.Get.offset + 0, rbp); 3755663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng AMD64AMode* am16 = AMD64AMode_IR(e->Iex.Get.offset + 16, rbp); 3756663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng addInstr(env, AMD64Instr_SseLdSt(True/*load*/, 16, vLo, am0)); 3757663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng addInstr(env, AMD64Instr_SseLdSt(True/*load*/, 16, vHi, am16)); 3758663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng *rHi = vHi; 3759663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng *rLo = vLo; 3760663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng return; 3761663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng } 3762663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 3763663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng if (e->tag == Iex_Load) { 3764663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng HReg vHi = newVRegV(env); 3765663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng HReg vLo = newVRegV(env); 3766663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng HReg rA = iselIntExpr_R(env, e->Iex.Load.addr); 3767663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng AMD64AMode* am0 = AMD64AMode_IR(0, rA); 3768663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng AMD64AMode* am16 = AMD64AMode_IR(16, rA); 3769663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng addInstr(env, AMD64Instr_SseLdSt(True/*load*/, 16, vLo, am0)); 3770663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng addInstr(env, AMD64Instr_SseLdSt(True/*load*/, 16, vHi, am16)); 3771663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng *rHi = vHi; 3772663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng *rLo = vLo; 3773663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng return; 3774663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng } 3775663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 3776663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng if (e->tag == Iex_Const) { 3777663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng vassert(e->Iex.Const.con->tag == Ico_V256); 3778663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng switch (e->Iex.Const.con->Ico.V256) { 3779663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng case 0x00000000: { 3780663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng HReg vHi = generate_zeroes_V128(env); 3781663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng HReg vLo = newVRegV(env); 3782663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng addInstr(env, mk_vMOVsd_RR(vHi, vLo)); 3783663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng *rHi = vHi; 3784663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng *rLo = vLo; 3785663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng return; 3786663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng } 3787663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng default: 3788663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng break; /* give up. Until such time as is necessary. */ 3789663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng } 3790663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng } 3791663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 3792663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng if (e->tag == Iex_Unop) { 3793663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng switch (e->Iex.Unop.op) { 3794663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 3795663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng case Iop_NotV256: { 3796663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng HReg argHi, argLo; 3797663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng iselDVecExpr(&argHi, &argLo, env, e->Iex.Unop.arg); 3798663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng *rHi = do_sse_NotV128(env, argHi); 3799663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng *rLo = do_sse_NotV128(env, argLo); 3800663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng return; 3801663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng } 3802663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 3803663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng case Iop_Recip32Fx8: op = Asse_RCPF; goto do_32Fx8_unary; 3804663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng case Iop_Sqrt32Fx8: op = Asse_SQRTF; goto do_32Fx8_unary; 3805663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng case Iop_RSqrt32Fx8: op = Asse_RSQRTF; goto do_32Fx8_unary; 3806663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng do_32Fx8_unary: 3807663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng { 3808663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng HReg argHi, argLo; 3809663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng iselDVecExpr(&argHi, &argLo, env, e->Iex.Unop.arg); 3810663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng HReg dstHi = newVRegV(env); 3811663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng HReg dstLo = newVRegV(env); 3812663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng addInstr(env, AMD64Instr_Sse32Fx4(op, argHi, dstHi)); 3813663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng addInstr(env, AMD64Instr_Sse32Fx4(op, argLo, dstLo)); 3814663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng *rHi = dstHi; 3815663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng *rLo = dstLo; 3816663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng return; 3817663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng } 3818663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 3819663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng case Iop_Sqrt64Fx4: op = Asse_SQRTF; goto do_64Fx4_unary; 3820663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng do_64Fx4_unary: 3821663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng { 3822663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng HReg argHi, argLo; 3823663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng iselDVecExpr(&argHi, &argLo, env, e->Iex.Unop.arg); 3824663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng HReg dstHi = newVRegV(env); 3825663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng HReg dstLo = newVRegV(env); 3826663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng addInstr(env, AMD64Instr_Sse64Fx2(op, argHi, dstHi)); 3827663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng addInstr(env, AMD64Instr_Sse64Fx2(op, argLo, dstLo)); 3828663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng *rHi = dstHi; 3829663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng *rLo = dstLo; 3830663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng return; 3831663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng } 3832663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 3833663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng case Iop_CmpNEZ64x4: { 3834663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng /* We can use SSE2 instructions for this. */ 3835663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng /* Same scheme as Iop_CmpNEZ64x2, except twice as wide 3836663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng (obviously). See comment on Iop_CmpNEZ64x2 for 3837663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng explanation of what's going on here. */ 3838663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng HReg argHi, argLo; 3839663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng iselDVecExpr(&argHi, &argLo, env, e->Iex.Unop.arg); 3840663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng HReg tmpHi = generate_zeroes_V128(env); 3841663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng HReg tmpLo = newVRegV(env); 3842663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng addInstr(env, mk_vMOVsd_RR(tmpHi, tmpLo)); 3843663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng HReg dstHi = newVRegV(env); 3844663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng HReg dstLo = newVRegV(env); 3845663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng addInstr(env, AMD64Instr_SseReRg(Asse_CMPEQ32, argHi, tmpHi)); 3846663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng addInstr(env, AMD64Instr_SseReRg(Asse_CMPEQ32, argLo, tmpLo)); 3847663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng tmpHi = do_sse_NotV128(env, tmpHi); 3848663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng tmpLo = do_sse_NotV128(env, tmpLo); 3849663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng addInstr(env, AMD64Instr_SseShuf(0xB1, tmpHi, dstHi)); 3850663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng addInstr(env, AMD64Instr_SseShuf(0xB1, tmpLo, dstLo)); 3851663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng addInstr(env, AMD64Instr_SseReRg(Asse_OR, tmpHi, dstHi)); 3852663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng addInstr(env, AMD64Instr_SseReRg(Asse_OR, tmpLo, dstLo)); 3853663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng *rHi = dstHi; 3854663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng *rLo = dstLo; 3855663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng return; 3856663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng } 3857663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 3858663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng case Iop_CmpNEZ32x8: op = Asse_CMPEQ32; goto do_CmpNEZ_vector; 3859436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case Iop_CmpNEZ16x16: op = Asse_CMPEQ16; goto do_CmpNEZ_vector; 3860436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case Iop_CmpNEZ8x32: op = Asse_CMPEQ8; goto do_CmpNEZ_vector; 3861663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng do_CmpNEZ_vector: 3862663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng { 3863663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng HReg argHi, argLo; 3864663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng iselDVecExpr(&argHi, &argLo, env, e->Iex.Unop.arg); 3865663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng HReg tmpHi = newVRegV(env); 3866663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng HReg tmpLo = newVRegV(env); 3867663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng HReg zero = generate_zeroes_V128(env); 3868663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng HReg dstHi, dstLo; 3869663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng addInstr(env, mk_vMOVsd_RR(argHi, tmpHi)); 3870663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng addInstr(env, mk_vMOVsd_RR(argLo, tmpLo)); 3871663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng addInstr(env, AMD64Instr_SseReRg(op, zero, tmpHi)); 3872663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng addInstr(env, AMD64Instr_SseReRg(op, zero, tmpLo)); 3873663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng dstHi = do_sse_NotV128(env, tmpHi); 3874663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng dstLo = do_sse_NotV128(env, tmpLo); 3875663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng *rHi = dstHi; 3876663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng *rLo = dstLo; 3877663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng return; 3878663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng } 3879663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 3880663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng default: 3881663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng break; 3882663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng } /* switch (e->Iex.Unop.op) */ 3883663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng } /* if (e->tag == Iex_Unop) */ 3884663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 3885663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng if (e->tag == Iex_Binop) { 3886663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng switch (e->Iex.Binop.op) { 3887663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 3888663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng case Iop_Max64Fx4: op = Asse_MAXF; goto do_64Fx4; 3889663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng case Iop_Min64Fx4: op = Asse_MINF; goto do_64Fx4; 3890663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng do_64Fx4: 3891663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng { 3892663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng HReg argLhi, argLlo, argRhi, argRlo; 3893663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng iselDVecExpr(&argLhi, &argLlo, env, e->Iex.Binop.arg1); 3894663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng iselDVecExpr(&argRhi, &argRlo, env, e->Iex.Binop.arg2); 3895663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng HReg dstHi = newVRegV(env); 3896663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng HReg dstLo = newVRegV(env); 3897663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng addInstr(env, mk_vMOVsd_RR(argLhi, dstHi)); 3898663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng addInstr(env, mk_vMOVsd_RR(argLlo, dstLo)); 3899663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng addInstr(env, AMD64Instr_Sse64Fx2(op, argRhi, dstHi)); 3900663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng addInstr(env, AMD64Instr_Sse64Fx2(op, argRlo, dstLo)); 3901663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng *rHi = dstHi; 3902663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng *rLo = dstLo; 3903663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng return; 3904663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng } 3905663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 3906663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng case Iop_Max32Fx8: op = Asse_MAXF; goto do_32Fx8; 3907663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng case Iop_Min32Fx8: op = Asse_MINF; goto do_32Fx8; 3908663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng do_32Fx8: 3909663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng { 3910663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng HReg argLhi, argLlo, argRhi, argRlo; 3911663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng iselDVecExpr(&argLhi, &argLlo, env, e->Iex.Binop.arg1); 3912663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng iselDVecExpr(&argRhi, &argRlo, env, e->Iex.Binop.arg2); 3913663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng HReg dstHi = newVRegV(env); 3914663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng HReg dstLo = newVRegV(env); 3915663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng addInstr(env, mk_vMOVsd_RR(argLhi, dstHi)); 3916663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng addInstr(env, mk_vMOVsd_RR(argLlo, dstLo)); 3917663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng addInstr(env, AMD64Instr_Sse32Fx4(op, argRhi, dstHi)); 3918663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng addInstr(env, AMD64Instr_Sse32Fx4(op, argRlo, dstLo)); 3919663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng *rHi = dstHi; 3920663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng *rLo = dstLo; 3921663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng return; 3922663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng } 3923663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 3924663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng case Iop_AndV256: op = Asse_AND; goto do_SseReRg; 3925663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng case Iop_OrV256: op = Asse_OR; goto do_SseReRg; 3926663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng case Iop_XorV256: op = Asse_XOR; goto do_SseReRg; 3927436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case Iop_Add8x32: op = Asse_ADD8; goto do_SseReRg; 3928436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case Iop_Add16x16: op = Asse_ADD16; goto do_SseReRg; 3929436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case Iop_Add32x8: op = Asse_ADD32; goto do_SseReRg; 3930436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case Iop_Add64x4: op = Asse_ADD64; goto do_SseReRg; 3931436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case Iop_QAdd8Sx32: op = Asse_QADD8S; goto do_SseReRg; 3932436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case Iop_QAdd16Sx16: op = Asse_QADD16S; goto do_SseReRg; 3933436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case Iop_QAdd8Ux32: op = Asse_QADD8U; goto do_SseReRg; 3934436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case Iop_QAdd16Ux16: op = Asse_QADD16U; goto do_SseReRg; 3935436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case Iop_Avg8Ux32: op = Asse_AVG8U; goto do_SseReRg; 3936436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case Iop_Avg16Ux16: op = Asse_AVG16U; goto do_SseReRg; 3937436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case Iop_CmpEQ8x32: op = Asse_CMPEQ8; goto do_SseReRg; 3938436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case Iop_CmpEQ16x16: op = Asse_CMPEQ16; goto do_SseReRg; 3939436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case Iop_CmpEQ32x8: op = Asse_CMPEQ32; goto do_SseReRg; 3940436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case Iop_CmpGT8Sx32: op = Asse_CMPGT8S; goto do_SseReRg; 3941436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case Iop_CmpGT16Sx16: op = Asse_CMPGT16S; goto do_SseReRg; 3942436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case Iop_CmpGT32Sx8: op = Asse_CMPGT32S; goto do_SseReRg; 3943436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case Iop_Max16Sx16: op = Asse_MAX16S; goto do_SseReRg; 3944436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case Iop_Max8Ux32: op = Asse_MAX8U; goto do_SseReRg; 3945436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case Iop_Min16Sx16: op = Asse_MIN16S; goto do_SseReRg; 3946436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case Iop_Min8Ux32: op = Asse_MIN8U; goto do_SseReRg; 3947436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case Iop_MulHi16Ux16: op = Asse_MULHI16U; goto do_SseReRg; 3948436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case Iop_MulHi16Sx16: op = Asse_MULHI16S; goto do_SseReRg; 3949436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case Iop_Mul16x16: op = Asse_MUL16; goto do_SseReRg; 3950436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case Iop_Sub8x32: op = Asse_SUB8; goto do_SseReRg; 3951436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case Iop_Sub16x16: op = Asse_SUB16; goto do_SseReRg; 3952436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case Iop_Sub32x8: op = Asse_SUB32; goto do_SseReRg; 3953436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case Iop_Sub64x4: op = Asse_SUB64; goto do_SseReRg; 3954436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case Iop_QSub8Sx32: op = Asse_QSUB8S; goto do_SseReRg; 3955436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case Iop_QSub16Sx16: op = Asse_QSUB16S; goto do_SseReRg; 3956436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case Iop_QSub8Ux32: op = Asse_QSUB8U; goto do_SseReRg; 3957436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case Iop_QSub16Ux16: op = Asse_QSUB16U; goto do_SseReRg; 3958663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng do_SseReRg: 3959663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng { 3960663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng HReg argLhi, argLlo, argRhi, argRlo; 3961663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng iselDVecExpr(&argLhi, &argLlo, env, e->Iex.Binop.arg1); 3962663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng iselDVecExpr(&argRhi, &argRlo, env, e->Iex.Binop.arg2); 3963663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng HReg dstHi = newVRegV(env); 3964663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng HReg dstLo = newVRegV(env); 3965663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng addInstr(env, mk_vMOVsd_RR(argLhi, dstHi)); 3966663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng addInstr(env, mk_vMOVsd_RR(argLlo, dstLo)); 3967663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng addInstr(env, AMD64Instr_SseReRg(op, argRhi, dstHi)); 3968663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng addInstr(env, AMD64Instr_SseReRg(op, argRlo, dstLo)); 3969663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng *rHi = dstHi; 3970663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng *rLo = dstLo; 3971663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng return; 3972663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng } 3973663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 3974436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case Iop_ShlN16x16: op = Asse_SHL16; goto do_SseShift; 3975436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case Iop_ShlN32x8: op = Asse_SHL32; goto do_SseShift; 3976436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case Iop_ShlN64x4: op = Asse_SHL64; goto do_SseShift; 3977436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case Iop_SarN16x16: op = Asse_SAR16; goto do_SseShift; 3978436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case Iop_SarN32x8: op = Asse_SAR32; goto do_SseShift; 3979436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case Iop_ShrN16x16: op = Asse_SHR16; goto do_SseShift; 3980436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case Iop_ShrN32x8: op = Asse_SHR32; goto do_SseShift; 3981436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case Iop_ShrN64x4: op = Asse_SHR64; goto do_SseShift; 3982436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov do_SseShift: { 3983436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov HReg gregHi, gregLo; 3984436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov iselDVecExpr(&gregHi, &gregLo, env, e->Iex.Binop.arg1); 3985436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov AMD64RMI* rmi = iselIntExpr_RMI(env, e->Iex.Binop.arg2); 3986436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov AMD64AMode* rsp0 = AMD64AMode_IR(0, hregAMD64_RSP()); 3987436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov HReg ereg = newVRegV(env); 3988436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov HReg dstHi = newVRegV(env); 3989436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov HReg dstLo = newVRegV(env); 3990436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov addInstr(env, AMD64Instr_Push(AMD64RMI_Imm(0))); 3991436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov addInstr(env, AMD64Instr_Push(rmi)); 3992436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov addInstr(env, AMD64Instr_SseLdSt(True/*load*/, 16, ereg, rsp0)); 3993436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov addInstr(env, mk_vMOVsd_RR(gregHi, dstHi)); 3994436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov addInstr(env, AMD64Instr_SseReRg(op, ereg, dstHi)); 3995436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov addInstr(env, mk_vMOVsd_RR(gregLo, dstLo)); 3996436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov addInstr(env, AMD64Instr_SseReRg(op, ereg, dstLo)); 3997436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov add_to_rsp(env, 16); 3998436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov *rHi = dstHi; 3999436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov *rLo = dstLo; 4000436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov return; 4001436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } 4002436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 4003663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng case Iop_V128HLtoV256: { 4004663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng *rHi = iselVecExpr(env, e->Iex.Binop.arg1); 4005663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng *rLo = iselVecExpr(env, e->Iex.Binop.arg2); 4006663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng return; 4007663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng } 4008663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 4009436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case Iop_Mul32x8: fn = (HWord)h_generic_calc_Mul32x4; 4010436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov goto do_SseAssistedBinary; 4011436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case Iop_Max32Sx8: fn = (HWord)h_generic_calc_Max32Sx4; 4012436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov goto do_SseAssistedBinary; 4013436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case Iop_Min32Sx8: fn = (HWord)h_generic_calc_Min32Sx4; 4014436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov goto do_SseAssistedBinary; 4015436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case Iop_Max32Ux8: fn = (HWord)h_generic_calc_Max32Ux4; 4016436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov goto do_SseAssistedBinary; 4017436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case Iop_Min32Ux8: fn = (HWord)h_generic_calc_Min32Ux4; 4018436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov goto do_SseAssistedBinary; 4019436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case Iop_Max16Ux16: fn = (HWord)h_generic_calc_Max16Ux8; 4020436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov goto do_SseAssistedBinary; 4021436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case Iop_Min16Ux16: fn = (HWord)h_generic_calc_Min16Ux8; 4022436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov goto do_SseAssistedBinary; 4023436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case Iop_Max8Sx32: fn = (HWord)h_generic_calc_Max8Sx16; 4024436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov goto do_SseAssistedBinary; 4025436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case Iop_Min8Sx32: fn = (HWord)h_generic_calc_Min8Sx16; 4026436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov goto do_SseAssistedBinary; 4027436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case Iop_CmpEQ64x4: fn = (HWord)h_generic_calc_CmpEQ64x2; 4028436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov goto do_SseAssistedBinary; 4029436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case Iop_CmpGT64Sx4: fn = (HWord)h_generic_calc_CmpGT64Sx2; 4030436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov goto do_SseAssistedBinary; 4031436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov do_SseAssistedBinary: { 4032436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /* RRRufff! RRRufff code is what we're generating here. Oh 4033436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov well. */ 4034436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov vassert(fn != 0); 4035436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov HReg dstHi = newVRegV(env); 4036436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov HReg dstLo = newVRegV(env); 4037436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov HReg argLhi, argLlo, argRhi, argRlo; 4038436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov iselDVecExpr(&argLhi, &argLlo, env, e->Iex.Binop.arg1); 4039436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov iselDVecExpr(&argRhi, &argRlo, env, e->Iex.Binop.arg2); 4040436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov HReg argp = newVRegI(env); 4041436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /* subq $160, %rsp -- make a space*/ 4042436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov sub_from_rsp(env, 160); 4043436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /* leaq 48(%rsp), %r_argp -- point into it */ 4044436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov addInstr(env, AMD64Instr_Lea64(AMD64AMode_IR(48, hregAMD64_RSP()), 4045436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov argp)); 4046436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /* andq $-16, %r_argp -- 16-align the pointer */ 4047436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov addInstr(env, AMD64Instr_Alu64R(Aalu_AND, 4048436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov AMD64RMI_Imm( ~(UInt)15 ), 4049436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov argp)); 4050436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /* Prepare 3 arg regs: 4051436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov leaq 0(%r_argp), %rdi 4052436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov leaq 16(%r_argp), %rsi 4053436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov leaq 32(%r_argp), %rdx 4054436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov */ 4055436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov addInstr(env, AMD64Instr_Lea64(AMD64AMode_IR(0, argp), 4056436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov hregAMD64_RDI())); 4057436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov addInstr(env, AMD64Instr_Lea64(AMD64AMode_IR(16, argp), 4058436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov hregAMD64_RSI())); 4059436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov addInstr(env, AMD64Instr_Lea64(AMD64AMode_IR(32, argp), 4060436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov hregAMD64_RDX())); 4061436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /* Store the two high args, at (%rsi) and (%rdx): 4062436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov movupd %argLhi, 0(%rsi) 4063436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov movupd %argRhi, 0(%rdx) 4064436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov */ 4065436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov addInstr(env, AMD64Instr_SseLdSt(False/*!isLoad*/, 16, argLhi, 4066436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov AMD64AMode_IR(0, hregAMD64_RSI()))); 4067436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov addInstr(env, AMD64Instr_SseLdSt(False/*!isLoad*/, 16, argRhi, 4068436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov AMD64AMode_IR(0, hregAMD64_RDX()))); 4069436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /* Store the two low args, at 48(%rsi) and 48(%rdx): 4070436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov movupd %argLlo, 48(%rsi) 4071436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov movupd %argRlo, 48(%rdx) 4072436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov */ 4073436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov addInstr(env, AMD64Instr_SseLdSt(False/*!isLoad*/, 16, argLlo, 4074436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov AMD64AMode_IR(48, hregAMD64_RSI()))); 4075436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov addInstr(env, AMD64Instr_SseLdSt(False/*!isLoad*/, 16, argRlo, 4076436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov AMD64AMode_IR(48, hregAMD64_RDX()))); 4077436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /* call the helper */ 4078436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov addInstr(env, AMD64Instr_Call( Acc_ALWAYS, (ULong)fn, 3, 4079436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov mk_RetLoc_simple(RLPri_None) )); 4080436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /* Prepare 3 arg regs: 4081436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov leaq 48(%r_argp), %rdi 4082436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov leaq 64(%r_argp), %rsi 4083436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov leaq 80(%r_argp), %rdx 4084436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov */ 4085436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov addInstr(env, AMD64Instr_Lea64(AMD64AMode_IR(48, argp), 4086436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov hregAMD64_RDI())); 4087436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov addInstr(env, AMD64Instr_Lea64(AMD64AMode_IR(64, argp), 4088436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov hregAMD64_RSI())); 4089436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov addInstr(env, AMD64Instr_Lea64(AMD64AMode_IR(80, argp), 4090436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov hregAMD64_RDX())); 4091436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /* call the helper */ 4092436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov addInstr(env, AMD64Instr_Call( Acc_ALWAYS, (ULong)fn, 3, 4093436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov mk_RetLoc_simple(RLPri_None) )); 4094436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /* fetch the result from memory, using %r_argp, which the 4095436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov register allocator will keep alive across the call. */ 4096436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov addInstr(env, AMD64Instr_SseLdSt(True/*isLoad*/, 16, dstHi, 4097436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov AMD64AMode_IR(0, argp))); 4098436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov addInstr(env, AMD64Instr_SseLdSt(True/*isLoad*/, 16, dstLo, 4099436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov AMD64AMode_IR(48, argp))); 4100436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /* and finally, clear the space */ 4101436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov add_to_rsp(env, 160); 4102436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov *rHi = dstHi; 4103436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov *rLo = dstLo; 4104436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov return; 4105436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } 4106436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 4107436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case Iop_Perm32x8: fn = (HWord)h_generic_calc_Perm32x8; 4108436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov goto do_SseAssistedBinary256; 4109436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov do_SseAssistedBinary256: { 4110436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /* RRRufff! RRRufff code is what we're generating here. Oh 4111436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov well. */ 4112436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov vassert(fn != 0); 4113436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov HReg dstHi = newVRegV(env); 4114436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov HReg dstLo = newVRegV(env); 4115436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov HReg argLhi, argLlo, argRhi, argRlo; 4116436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov iselDVecExpr(&argLhi, &argLlo, env, e->Iex.Binop.arg1); 4117436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov iselDVecExpr(&argRhi, &argRlo, env, e->Iex.Binop.arg2); 4118436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov HReg argp = newVRegI(env); 4119436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /* subq $160, %rsp -- make a space*/ 4120436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov sub_from_rsp(env, 160); 4121436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /* leaq 48(%rsp), %r_argp -- point into it */ 4122436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov addInstr(env, AMD64Instr_Lea64(AMD64AMode_IR(48, hregAMD64_RSP()), 4123436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov argp)); 4124436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /* andq $-16, %r_argp -- 16-align the pointer */ 4125436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov addInstr(env, AMD64Instr_Alu64R(Aalu_AND, 4126436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov AMD64RMI_Imm( ~(UInt)15 ), 4127436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov argp)); 4128436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /* Prepare 3 arg regs: 4129436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov leaq 0(%r_argp), %rdi 4130436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov leaq 32(%r_argp), %rsi 4131436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov leaq 64(%r_argp), %rdx 4132436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov */ 4133436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov addInstr(env, AMD64Instr_Lea64(AMD64AMode_IR(0, argp), 4134436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov hregAMD64_RDI())); 4135436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov addInstr(env, AMD64Instr_Lea64(AMD64AMode_IR(32, argp), 4136436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov hregAMD64_RSI())); 4137436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov addInstr(env, AMD64Instr_Lea64(AMD64AMode_IR(64, argp), 4138436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov hregAMD64_RDX())); 4139436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /* Store the two args, at (%rsi) and (%rdx): 4140436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov movupd %argLlo, 0(%rsi) 4141436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov movupd %argLhi, 16(%rsi) 4142436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov movupd %argRlo, 0(%rdx) 4143436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov movupd %argRhi, 16(%rdx) 4144436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov */ 4145436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov addInstr(env, AMD64Instr_SseLdSt(False/*!isLoad*/, 16, argLlo, 4146436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov AMD64AMode_IR(0, hregAMD64_RSI()))); 4147436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov addInstr(env, AMD64Instr_SseLdSt(False/*!isLoad*/, 16, argLhi, 4148436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov AMD64AMode_IR(16, hregAMD64_RSI()))); 4149436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov addInstr(env, AMD64Instr_SseLdSt(False/*!isLoad*/, 16, argRlo, 4150436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov AMD64AMode_IR(0, hregAMD64_RDX()))); 4151436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov addInstr(env, AMD64Instr_SseLdSt(False/*!isLoad*/, 16, argRhi, 4152436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov AMD64AMode_IR(16, hregAMD64_RDX()))); 4153436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /* call the helper */ 4154436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov addInstr(env, AMD64Instr_Call( Acc_ALWAYS, (ULong)fn, 3, 4155436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov mk_RetLoc_simple(RLPri_None) )); 4156436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /* fetch the result from memory, using %r_argp, which the 4157436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov register allocator will keep alive across the call. */ 4158436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov addInstr(env, AMD64Instr_SseLdSt(True/*isLoad*/, 16, dstLo, 4159436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov AMD64AMode_IR(0, argp))); 4160436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov addInstr(env, AMD64Instr_SseLdSt(True/*isLoad*/, 16, dstHi, 4161436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov AMD64AMode_IR(16, argp))); 4162436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /* and finally, clear the space */ 4163436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov add_to_rsp(env, 160); 4164436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov *rHi = dstHi; 4165436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov *rLo = dstLo; 4166436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov return; 4167436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } 4168436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 4169663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng default: 4170663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng break; 4171663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng } /* switch (e->Iex.Binop.op) */ 4172663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng } /* if (e->tag == Iex_Binop) */ 4173663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 4174436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov if (e->tag == Iex_Triop) { 4175436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov IRTriop *triop = e->Iex.Triop.details; 4176436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov switch (triop->op) { 4177436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 4178436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case Iop_Add64Fx4: op = Asse_ADDF; goto do_64Fx4_w_rm; 4179436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case Iop_Sub64Fx4: op = Asse_SUBF; goto do_64Fx4_w_rm; 4180436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case Iop_Mul64Fx4: op = Asse_MULF; goto do_64Fx4_w_rm; 4181436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case Iop_Div64Fx4: op = Asse_DIVF; goto do_64Fx4_w_rm; 4182436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov do_64Fx4_w_rm: 4183436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov { 4184436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov HReg argLhi, argLlo, argRhi, argRlo; 4185436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov iselDVecExpr(&argLhi, &argLlo, env, triop->arg2); 4186436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov iselDVecExpr(&argRhi, &argRlo, env, triop->arg3); 4187436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov HReg dstHi = newVRegV(env); 4188436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov HReg dstLo = newVRegV(env); 4189436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov addInstr(env, mk_vMOVsd_RR(argLhi, dstHi)); 4190436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov addInstr(env, mk_vMOVsd_RR(argLlo, dstLo)); 4191436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /* XXXROUNDINGFIXME */ 4192436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /* set roundingmode here */ 4193436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov addInstr(env, AMD64Instr_Sse64Fx2(op, argRhi, dstHi)); 4194436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov addInstr(env, AMD64Instr_Sse64Fx2(op, argRlo, dstLo)); 4195436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov *rHi = dstHi; 4196436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov *rLo = dstLo; 4197436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov return; 4198436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } 4199436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 4200436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case Iop_Add32Fx8: op = Asse_ADDF; goto do_32Fx8_w_rm; 4201436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case Iop_Sub32Fx8: op = Asse_SUBF; goto do_32Fx8_w_rm; 4202436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case Iop_Mul32Fx8: op = Asse_MULF; goto do_32Fx8_w_rm; 4203436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case Iop_Div32Fx8: op = Asse_DIVF; goto do_32Fx8_w_rm; 4204436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov do_32Fx8_w_rm: 4205436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov { 4206436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov HReg argLhi, argLlo, argRhi, argRlo; 4207436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov iselDVecExpr(&argLhi, &argLlo, env, triop->arg2); 4208436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov iselDVecExpr(&argRhi, &argRlo, env, triop->arg3); 4209436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov HReg dstHi = newVRegV(env); 4210436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov HReg dstLo = newVRegV(env); 4211436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov addInstr(env, mk_vMOVsd_RR(argLhi, dstHi)); 4212436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov addInstr(env, mk_vMOVsd_RR(argLlo, dstLo)); 4213436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /* XXXROUNDINGFIXME */ 4214436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /* set roundingmode here */ 4215436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov addInstr(env, AMD64Instr_Sse32Fx4(op, argRhi, dstHi)); 4216436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov addInstr(env, AMD64Instr_Sse32Fx4(op, argRlo, dstLo)); 4217436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov *rHi = dstHi; 4218436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov *rLo = dstLo; 4219436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov return; 4220436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } 4221436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 4222436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov default: 4223436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov break; 4224436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } /* switch (triop->op) */ 4225436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } /* if (e->tag == Iex_Triop) */ 4226436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 4227436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 4228663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng if (e->tag == Iex_Qop && e->Iex.Qop.details->op == Iop_64x4toV256) { 4229663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng HReg rsp = hregAMD64_RSP(); 4230663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng HReg vHi = newVRegV(env); 4231663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng HReg vLo = newVRegV(env); 4232663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng AMD64AMode* m8_rsp = AMD64AMode_IR(-8, rsp); 4233663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng AMD64AMode* m16_rsp = AMD64AMode_IR(-16, rsp); 4234663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng /* arg1 is the most significant (Q3), arg4 the least (Q0) */ 4235663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng /* Get all the args into regs, before messing with the stack. */ 4236663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng AMD64RI* q3 = iselIntExpr_RI(env, e->Iex.Qop.details->arg1); 4237663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng AMD64RI* q2 = iselIntExpr_RI(env, e->Iex.Qop.details->arg2); 4238663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng AMD64RI* q1 = iselIntExpr_RI(env, e->Iex.Qop.details->arg3); 4239663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng AMD64RI* q0 = iselIntExpr_RI(env, e->Iex.Qop.details->arg4); 4240663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng /* less significant lane (Q2) at the lower address (-16(rsp)) */ 4241663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng addInstr(env, AMD64Instr_Alu64M(Aalu_MOV, q3, m8_rsp)); 4242663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng addInstr(env, AMD64Instr_Alu64M(Aalu_MOV, q2, m16_rsp)); 4243663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng addInstr(env, AMD64Instr_SseLdSt(True/*load*/, 16, vHi, m16_rsp)); 4244663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng /* and then the lower half .. */ 4245663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng addInstr(env, AMD64Instr_Alu64M(Aalu_MOV, q1, m8_rsp)); 4246663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng addInstr(env, AMD64Instr_Alu64M(Aalu_MOV, q0, m16_rsp)); 4247663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng addInstr(env, AMD64Instr_SseLdSt(True/*load*/, 16, vLo, m16_rsp)); 4248663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng *rHi = vHi; 4249663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng *rLo = vLo; 4250663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng return; 4251663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng } 4252663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 4253436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov if (e->tag == Iex_ITE) { 4254436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov HReg r1Hi, r1Lo, r0Hi, r0Lo; 4255436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov iselDVecExpr(&r1Hi, &r1Lo, env, e->Iex.ITE.iftrue); 4256436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov iselDVecExpr(&r0Hi, &r0Lo, env, e->Iex.ITE.iffalse); 4257436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov HReg dstHi = newVRegV(env); 4258436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov HReg dstLo = newVRegV(env); 4259436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov addInstr(env, mk_vMOVsd_RR(r1Hi,dstHi)); 4260436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov addInstr(env, mk_vMOVsd_RR(r1Lo,dstLo)); 4261436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov AMD64CondCode cc = iselCondCode(env, e->Iex.ITE.cond); 4262436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov addInstr(env, AMD64Instr_SseCMov(cc ^ 1, r0Hi, dstHi)); 4263436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov addInstr(env, AMD64Instr_SseCMov(cc ^ 1, r0Lo, dstLo)); 4264436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov *rHi = dstHi; 4265436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov *rLo = dstLo; 4266436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov return; 4267436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } 4268436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 4269663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng //avx_fail: 4270663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng vex_printf("iselDVecExpr (amd64, subarch = %s): can't reduce\n", 4271663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng LibVEX_ppVexHwCaps(VexArchAMD64, env->hwcaps)); 4272663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng ppIRExpr(e); 4273663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng vpanic("iselDVecExpr_wrk"); 4274663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng} 4275663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 4276663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 4277663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/*---------------------------------------------------------*/ 4278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- ISEL: Statements ---*/ 4279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------*/ 4280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 4281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void iselStmt ( ISelEnv* env, IRStmt* stmt ) 4282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 4283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (vex_traceflags & VEX_TRACE_VCODE) { 4284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vex_printf("\n-- "); 4285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ppIRStmt(stmt); 4286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vex_printf("\n"); 4287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 4289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (stmt->tag) { 4290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 4291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* --------- STORE --------- */ 4292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Ist_Store: { 4293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRType tya = typeOfIRExpr(env->type_env, stmt->Ist.Store.addr); 4294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRType tyd = typeOfIRExpr(env->type_env, stmt->Ist.Store.data); 4295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IREndness end = stmt->Ist.Store.end; 4296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 4297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (tya != Ity_I64 || end != Iend_LE) 4298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown goto stmt_fail; 4299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 4300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (tyd == Ity_I64) { 4301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown AMD64AMode* am = iselIntExpr_AMode(env, stmt->Ist.Store.addr); 4302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown AMD64RI* ri = iselIntExpr_RI(env, stmt->Ist.Store.data); 4303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_Alu64M(Aalu_MOV,ri,am)); 4304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return; 4305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (tyd == Ity_I8 || tyd == Ity_I16 || tyd == Ity_I32) { 4307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown AMD64AMode* am = iselIntExpr_AMode(env, stmt->Ist.Store.addr); 4308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg r = iselIntExpr_R(env, stmt->Ist.Store.data); 4309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_Store( 4310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown toUChar(tyd==Ity_I8 ? 1 : (tyd==Ity_I16 ? 2 : 4)), 4311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown r,am)); 4312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return; 4313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (tyd == Ity_F64) { 4315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown AMD64AMode* am = iselIntExpr_AMode(env, stmt->Ist.Store.addr); 4316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg r = iselDblExpr(env, stmt->Ist.Store.data); 4317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_SseLdSt(False/*store*/, 8, r, am)); 4318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return; 4319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (tyd == Ity_F32) { 4321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown AMD64AMode* am = iselIntExpr_AMode(env, stmt->Ist.Store.addr); 4322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg r = iselFltExpr(env, stmt->Ist.Store.data); 4323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_SseLdSt(False/*store*/, 4, r, am)); 4324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return; 4325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (tyd == Ity_V128) { 4327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown AMD64AMode* am = iselIntExpr_AMode(env, stmt->Ist.Store.addr); 4328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg r = iselVecExpr(env, stmt->Ist.Store.data); 4329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_SseLdSt(False/*store*/, 16, r, am)); 4330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return; 4331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4332663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng if (tyd == Ity_V256) { 4333663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng HReg rA = iselIntExpr_R(env, stmt->Ist.Store.addr); 4334663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng AMD64AMode* am0 = AMD64AMode_IR(0, rA); 4335663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng AMD64AMode* am16 = AMD64AMode_IR(16, rA); 4336663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng HReg vHi, vLo; 4337663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng iselDVecExpr(&vHi, &vLo, env, stmt->Ist.Store.data); 4338663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng addInstr(env, AMD64Instr_SseLdSt(False/*store*/, 16, vLo, am0)); 4339663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng addInstr(env, AMD64Instr_SseLdSt(False/*store*/, 16, vHi, am16)); 4340663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng return; 4341663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng } 4342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 4343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 4345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* --------- PUT --------- */ 4346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Ist_Put: { 4347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRType ty = typeOfIRExpr(env->type_env, stmt->Ist.Put.data); 4348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (ty == Ity_I64) { 4349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* We're going to write to memory, so compute the RHS into an 4350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown AMD64RI. */ 4351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown AMD64RI* ri = iselIntExpr_RI(env, stmt->Ist.Put.data); 4352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, 4353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown AMD64Instr_Alu64M( 4354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Aalu_MOV, 4355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ri, 4356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown AMD64AMode_IR(stmt->Ist.Put.offset, 4357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown hregAMD64_RBP()) 4358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown )); 4359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return; 4360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (ty == Ity_I8 || ty == Ity_I16 || ty == Ity_I32) { 4362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg r = iselIntExpr_R(env, stmt->Ist.Put.data); 4363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_Store( 4364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown toUChar(ty==Ity_I8 ? 1 : (ty==Ity_I16 ? 2 : 4)), 4365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown r, 4366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown AMD64AMode_IR(stmt->Ist.Put.offset, 4367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown hregAMD64_RBP()))); 4368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return; 4369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (ty == Ity_F32) { 4371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg f32 = iselFltExpr(env, stmt->Ist.Put.data); 4372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown AMD64AMode* am = AMD64AMode_IR(stmt->Ist.Put.offset, hregAMD64_RBP()); 4373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown set_SSE_rounding_default(env); /* paranoia */ 4374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_SseLdSt( False/*store*/, 4, f32, am )); 4375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return; 4376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (ty == Ity_F64) { 4378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg f64 = iselDblExpr(env, stmt->Ist.Put.data); 4379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown AMD64AMode* am = AMD64AMode_IR( stmt->Ist.Put.offset, 4380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown hregAMD64_RBP() ); 4381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_SseLdSt( False/*store*/, 8, f64, am )); 4382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return; 4383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4384663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng if (ty == Ity_V128) { 4385663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng HReg vec = iselVecExpr(env, stmt->Ist.Put.data); 4386663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng AMD64AMode* am = AMD64AMode_IR(stmt->Ist.Put.offset, 4387663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng hregAMD64_RBP()); 4388663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng addInstr(env, AMD64Instr_SseLdSt(False/*store*/, 16, vec, am)); 4389663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng return; 4390663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng } 4391663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng if (ty == Ity_V256) { 4392663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng HReg vHi, vLo; 4393663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng iselDVecExpr(&vHi, &vLo, env, stmt->Ist.Put.data); 4394663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng HReg rbp = hregAMD64_RBP(); 4395663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng AMD64AMode* am0 = AMD64AMode_IR(stmt->Ist.Put.offset + 0, rbp); 4396663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng AMD64AMode* am16 = AMD64AMode_IR(stmt->Ist.Put.offset + 16, rbp); 4397663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng addInstr(env, AMD64Instr_SseLdSt(False/*store*/, 16, vLo, am0)); 4398663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng addInstr(env, AMD64Instr_SseLdSt(False/*store*/, 16, vHi, am16)); 4399663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng return; 4400663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng } 4401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 4402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 4404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* --------- Indexed PUT --------- */ 4405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Ist_PutI: { 4406663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng IRPutI *puti = stmt->Ist.PutI.details; 4407663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 4408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown AMD64AMode* am 4409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown = genGuestArrayOffset( 4410663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng env, puti->descr, 4411663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng puti->ix, puti->bias ); 4412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 4413663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng IRType ty = typeOfIRExpr(env->type_env, puti->data); 4414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (ty == Ity_F64) { 4415663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng HReg val = iselDblExpr(env, puti->data); 4416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_SseLdSt( False/*store*/, 8, val, am )); 4417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return; 4418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (ty == Ity_I8) { 4420663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng HReg r = iselIntExpr_R(env, puti->data); 4421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_Store( 1, r, am )); 4422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return; 4423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (ty == Ity_I64) { 4425663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng AMD64RI* ri = iselIntExpr_RI(env, puti->data); 4426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_Alu64M( Aalu_MOV, ri, am )); 4427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return; 4428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 4430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 4432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* --------- TMP --------- */ 4433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Ist_WrTmp: { 4434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRTemp tmp = stmt->Ist.WrTmp.tmp; 4435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRType ty = typeOfIRTemp(env->type_env, tmp); 4436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 4437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* optimisation: if stmt->Ist.WrTmp.data is Add64(..,..), 4438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown compute it into an AMode and then use LEA. This usually 4439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown produces fewer instructions, often because (for memcheck 4440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown created IR) we get t = address-expression, (t is later used 4441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown twice) and so doing this naturally turns address-expression 4442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown back into an AMD64 amode. */ 4443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (ty == Ity_I64 4444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && stmt->Ist.WrTmp.data->tag == Iex_Binop 4445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && stmt->Ist.WrTmp.data->Iex.Binop.op == Iop_Add64) { 4446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown AMD64AMode* am = iselIntExpr_AMode(env, stmt->Ist.WrTmp.data); 4447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg dst = lookupIRTemp(env, tmp); 4448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (am->tag == Aam_IR && am->Aam.IR.imm == 0) { 4449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Hmm, iselIntExpr_AMode wimped out and just computed the 4450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown value into a register. Just emit a normal reg-reg move 4451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown so reg-alloc can coalesce it away in the usual way. */ 4452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg src = am->Aam.IR.reg; 4453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_Alu64R(Aalu_MOV, AMD64RMI_Reg(src), dst)); 4454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 4455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_Lea64(am,dst)); 4456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return; 4458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 4460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (ty == Ity_I64 || ty == Ity_I32 4461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown || ty == Ity_I16 || ty == Ity_I8) { 4462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown AMD64RMI* rmi = iselIntExpr_RMI(env, stmt->Ist.WrTmp.data); 4463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg dst = lookupIRTemp(env, tmp); 4464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_Alu64R(Aalu_MOV,rmi,dst)); 4465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return; 4466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (ty == Ity_I128) { 4468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg rHi, rLo, dstHi, dstLo; 4469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown iselInt128Expr(&rHi,&rLo, env, stmt->Ist.WrTmp.data); 4470663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng lookupIRTempPair( &dstHi, &dstLo, env, tmp); 4471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, mk_iMOVsd_RR(rHi,dstHi) ); 4472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, mk_iMOVsd_RR(rLo,dstLo) ); 4473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return; 4474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (ty == Ity_I1) { 4476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown AMD64CondCode cond = iselCondCode(env, stmt->Ist.WrTmp.data); 4477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg dst = lookupIRTemp(env, tmp); 4478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_Set64(cond, dst)); 4479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return; 4480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (ty == Ity_F64) { 4482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg dst = lookupIRTemp(env, tmp); 4483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg src = iselDblExpr(env, stmt->Ist.WrTmp.data); 4484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, mk_vMOVsd_RR(src, dst)); 4485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return; 4486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (ty == Ity_F32) { 4488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg dst = lookupIRTemp(env, tmp); 4489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg src = iselFltExpr(env, stmt->Ist.WrTmp.data); 4490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, mk_vMOVsd_RR(src, dst)); 4491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return; 4492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (ty == Ity_V128) { 4494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg dst = lookupIRTemp(env, tmp); 4495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg src = iselVecExpr(env, stmt->Ist.WrTmp.data); 4496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, mk_vMOVsd_RR(src, dst)); 4497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return; 4498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4499663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng if (ty == Ity_V256) { 4500663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng HReg rHi, rLo, dstHi, dstLo; 4501663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng iselDVecExpr(&rHi,&rLo, env, stmt->Ist.WrTmp.data); 4502663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng lookupIRTempPair( &dstHi, &dstLo, env, tmp); 4503663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng addInstr(env, mk_vMOVsd_RR(rHi,dstHi) ); 4504663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng addInstr(env, mk_vMOVsd_RR(rLo,dstLo) ); 4505663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng return; 4506663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng } 4507ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 4508ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 4510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* --------- Call to DIRTY helper --------- */ 4511ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Ist_Dirty: { 4512ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRDirty* d = stmt->Ist.Dirty.details; 4513ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 4514436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /* Figure out the return type, if any. */ 4515436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov IRType retty = Ity_INVALID; 4516436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov if (d->tmp != IRTemp_INVALID) 4517436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov retty = typeOfIRTemp(env->type_env, d->tmp); 4518436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 4519436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /* Throw out any return types we don't know about. */ 4520436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov Bool retty_ok = False; 4521436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov switch (retty) { 4522436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case Ity_INVALID: /* function doesn't return anything */ 4523436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case Ity_I64: case Ity_I32: case Ity_I16: case Ity_I8: 4524436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case Ity_V128: case Ity_V256: 4525436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov retty_ok = True; break; 4526436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov default: 4527436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov break; 4528436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } 4529436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov if (!retty_ok) 4530436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov break; /* will go to stmt_fail: */ 4531ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 4532436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /* Marshal args, do the call, and set the return value to 4533436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 0x555..555 if this is a conditional call that returns a value 4534436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov and the call is skipped. */ 4535436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov UInt addToSp = 0; 4536436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov RetLoc rloc = mk_RetLoc_INVALID(); 4537436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov doHelperCall( &addToSp, &rloc, env, d->guard, d->cee, retty, d->args ); 4538436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov vassert(is_sane_RetLoc(rloc)); 4539ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 4540ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Now figure out what to do with the returned value, if any. */ 4541436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov switch (retty) { 4542436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case Ity_INVALID: { 4543436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /* No return value. Nothing to do. */ 4544436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov vassert(d->tmp == IRTemp_INVALID); 4545436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov vassert(rloc.pri == RLPri_None); 4546436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov vassert(addToSp == 0); 4547436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov return; 4548436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } 4549436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case Ity_I64: case Ity_I32: case Ity_I16: case Ity_I8: { 4550436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /* The returned value is in %rax. Park it in the register 4551436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov associated with tmp. */ 4552436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov vassert(rloc.pri == RLPri_Int); 4553436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov vassert(addToSp == 0); 4554436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov HReg dst = lookupIRTemp(env, d->tmp); 4555436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov addInstr(env, mk_iMOVsd_RR(hregAMD64_RAX(),dst) ); 4556436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov return; 4557436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } 4558436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case Ity_V128: { 4559436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /* The returned value is on the stack, and rloc.spOff 4560436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov tells us where. Fish it off the stack and then move 4561436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov the stack pointer upwards to clear it, as directed by 4562436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov doHelperCall. */ 4563436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov vassert(rloc.pri == RLPri_V128SpRel); 4564436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov vassert(addToSp >= 16); 4565436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov HReg dst = lookupIRTemp(env, d->tmp); 4566436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov AMD64AMode* am = AMD64AMode_IR(rloc.spOff, hregAMD64_RSP()); 4567436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov addInstr(env, AMD64Instr_SseLdSt( True/*load*/, 16, dst, am )); 4568436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov add_to_rsp(env, addToSp); 4569436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov return; 4570436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } 4571436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case Ity_V256: { 4572436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /* See comments for Ity_V128. */ 4573436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov vassert(rloc.pri == RLPri_V256SpRel); 4574436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov vassert(addToSp >= 32); 4575436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov HReg dstLo, dstHi; 4576436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov lookupIRTempPair(&dstHi, &dstLo, env, d->tmp); 4577436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov AMD64AMode* amLo = AMD64AMode_IR(rloc.spOff, hregAMD64_RSP()); 4578436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov addInstr(env, AMD64Instr_SseLdSt( True/*load*/, 16, dstLo, amLo )); 4579436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov AMD64AMode* amHi = AMD64AMode_IR(rloc.spOff+16, hregAMD64_RSP()); 4580436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov addInstr(env, AMD64Instr_SseLdSt( True/*load*/, 16, dstHi, amHi )); 4581436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov add_to_rsp(env, addToSp); 4582436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov return; 4583436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } 4584436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov default: 4585436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /*NOTREACHED*/ 4586436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov vassert(0); 4587ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 4589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 4591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* --------- MEM FENCE --------- */ 4592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Ist_MBE: 4593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (stmt->Ist.MBE.event) { 4594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Imbe_Fence: 4595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_MFence()); 4596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return; 4597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: 4598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 4599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 4601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 4602ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* --------- ACAS --------- */ 4603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Ist_CAS: 4604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (stmt->Ist.CAS.details->oldHi == IRTemp_INVALID) { 4605ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* "normal" singleton CAS */ 4606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UChar sz; 4607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRCAS* cas = stmt->Ist.CAS.details; 4608ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRType ty = typeOfIRExpr(env->type_env, cas->dataLo); 4609ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* get: cas->expd into %rax, and cas->data into %rbx */ 4610ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown AMD64AMode* am = iselIntExpr_AMode(env, cas->addr); 4611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg rData = iselIntExpr_R(env, cas->dataLo); 4612ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg rExpd = iselIntExpr_R(env, cas->expdLo); 4613ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg rOld = lookupIRTemp(env, cas->oldLo); 4614ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert(cas->expdHi == NULL); 4615ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert(cas->dataHi == NULL); 4616ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, mk_iMOVsd_RR(rExpd, rOld)); 4617ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, mk_iMOVsd_RR(rExpd, hregAMD64_RAX())); 4618ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, mk_iMOVsd_RR(rData, hregAMD64_RBX())); 4619ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (ty) { 4620ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Ity_I64: sz = 8; break; 4621ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Ity_I32: sz = 4; break; 4622ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Ity_I16: sz = 2; break; 4623ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Ity_I8: sz = 1; break; 4624ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: goto unhandled_cas; 4625ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4626ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_ACAS(am, sz)); 4627ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_CMov64( 4628ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Acc_NZ, AMD64RM_Reg(hregAMD64_RAX()), rOld)); 4629ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return; 4630ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 4631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* double CAS */ 4632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UChar sz; 4633ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRCAS* cas = stmt->Ist.CAS.details; 4634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRType ty = typeOfIRExpr(env->type_env, cas->dataLo); 4635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* only 32-bit and 64-bit allowed in this case */ 4636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* get: cas->expdLo into %rax, and cas->dataLo into %rbx */ 4637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* get: cas->expdHi into %rdx, and cas->dataHi into %rcx */ 4638ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown AMD64AMode* am = iselIntExpr_AMode(env, cas->addr); 4639ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg rDataHi = iselIntExpr_R(env, cas->dataHi); 4640ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg rDataLo = iselIntExpr_R(env, cas->dataLo); 4641ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg rExpdHi = iselIntExpr_R(env, cas->expdHi); 4642ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg rExpdLo = iselIntExpr_R(env, cas->expdLo); 4643ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg rOldHi = lookupIRTemp(env, cas->oldHi); 4644ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg rOldLo = lookupIRTemp(env, cas->oldLo); 4645ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (ty) { 4646ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Ity_I64: 4647ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!(env->hwcaps & VEX_HWCAPS_AMD64_CX16)) 4648ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown goto unhandled_cas; /* we'd have to generate 4649ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown cmpxchg16b, but the host 4650ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown doesn't support that */ 4651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sz = 8; 4652ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 4653ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Ity_I32: 4654ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sz = 4; 4655ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 4656ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: 4657ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown goto unhandled_cas; 4658ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4659ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, mk_iMOVsd_RR(rExpdHi, rOldHi)); 4660ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, mk_iMOVsd_RR(rExpdLo, rOldLo)); 4661ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, mk_iMOVsd_RR(rExpdHi, hregAMD64_RDX())); 4662ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, mk_iMOVsd_RR(rExpdLo, hregAMD64_RAX())); 4663ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, mk_iMOVsd_RR(rDataHi, hregAMD64_RCX())); 4664ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, mk_iMOVsd_RR(rDataLo, hregAMD64_RBX())); 4665ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, AMD64Instr_DACAS(am, sz)); 4666ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, 4667ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown AMD64Instr_CMov64( 4668ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Acc_NZ, AMD64RM_Reg(hregAMD64_RDX()), rOldHi)); 4669ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, 4670ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown AMD64Instr_CMov64( 4671ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Acc_NZ, AMD64RM_Reg(hregAMD64_RAX()), rOldLo)); 4672ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return; 4673ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4674ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown unhandled_cas: 4675ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 4676ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 4677ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* --------- INSTR MARK --------- */ 4678ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Doesn't generate any executable code ... */ 4679ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Ist_IMark: 4680ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return; 4681ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 4682ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* --------- ABI HINT --------- */ 4683ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* These have no meaning (denotation in the IR) and so we ignore 4684ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown them ... if any actually made it this far. */ 4685ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Ist_AbiHint: 4686ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return; 4687ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 4688ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* --------- NO-OP --------- */ 4689ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Ist_NoOp: 4690ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return; 4691ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 4692ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* --------- EXIT --------- */ 4693ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Ist_Exit: { 4694ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (stmt->Ist.Exit.dst->tag != Ico_U64) 4695ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vpanic("iselStmt(amd64): Ist_Exit: dst is not a 64-bit value"); 4696663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 4697663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng AMD64CondCode cc = iselCondCode(env, stmt->Ist.Exit.guard); 4698663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng AMD64AMode* amRIP = AMD64AMode_IR(stmt->Ist.Exit.offsIP, 4699663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng hregAMD64_RBP()); 4700663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 4701663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng /* Case: boring transfer to known address */ 4702663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng if (stmt->Ist.Exit.jk == Ijk_Boring) { 4703663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng if (env->chainingAllowed) { 4704663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng /* .. almost always true .. */ 4705663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng /* Skip the event check at the dst if this is a forwards 4706663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng edge. */ 4707663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng Bool toFastEP 4708663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng = ((Addr64)stmt->Ist.Exit.dst->Ico.U64) > env->max_ga; 4709663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng if (0) vex_printf("%s", toFastEP ? "Y" : ","); 4710663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng addInstr(env, AMD64Instr_XDirect(stmt->Ist.Exit.dst->Ico.U64, 4711663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng amRIP, cc, toFastEP)); 4712663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng } else { 4713663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng /* .. very occasionally .. */ 4714663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng /* We can't use chaining, so ask for an assisted transfer, 4715663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng as that's the only alternative that is allowable. */ 4716663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng HReg r = iselIntExpr_R(env, IRExpr_Const(stmt->Ist.Exit.dst)); 4717663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng addInstr(env, AMD64Instr_XAssisted(r, amRIP, cc, Ijk_Boring)); 4718663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng } 4719663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng return; 4720663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng } 4721663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 4722663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng /* Case: assisted transfer to arbitrary address */ 4723663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng switch (stmt->Ist.Exit.jk) { 4724663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng /* Keep this list in sync with that in iselNext below */ 4725663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng case Ijk_ClientReq: 4726663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng case Ijk_EmWarn: 4727663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng case Ijk_NoDecode: 4728663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng case Ijk_NoRedir: 4729663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng case Ijk_SigSEGV: 4730663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng case Ijk_SigTRAP: 4731663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng case Ijk_Sys_syscall: 4732eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov case Ijk_InvalICache: 4733663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng case Ijk_Yield: 4734663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng { 4735663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng HReg r = iselIntExpr_R(env, IRExpr_Const(stmt->Ist.Exit.dst)); 4736663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng addInstr(env, AMD64Instr_XAssisted(r, amRIP, cc, stmt->Ist.Exit.jk)); 4737663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng return; 4738663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng } 4739663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng default: 4740663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng break; 4741663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng } 4742663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 4743663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng /* Do we ever expect to see any other kind? */ 4744663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng goto stmt_fail; 4745ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4746ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 4747ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: break; 4748ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4749ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown stmt_fail: 4750ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ppIRStmt(stmt); 4751ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vpanic("iselStmt(amd64)"); 4752ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 4753ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 4754ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 4755ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------*/ 4756ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- ISEL: Basic block terminators (Nexts) ---*/ 4757ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------*/ 4758ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 4759663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic void iselNext ( ISelEnv* env, 4760663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng IRExpr* next, IRJumpKind jk, Int offsIP ) 4761ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 4762ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (vex_traceflags & VEX_TRACE_VCODE) { 4763663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng vex_printf( "\n-- PUT(%d) = ", offsIP); 4764663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng ppIRExpr( next ); 4765663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng vex_printf( "; exit-"); 4766ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ppIRJumpKind(jk); 4767663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng vex_printf( "\n"); 4768ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4769663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 4770663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng /* Case: boring transfer to known address */ 4771663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng if (next->tag == Iex_Const) { 4772663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng IRConst* cdst = next->Iex.Const.con; 4773663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng vassert(cdst->tag == Ico_U64); 4774663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng if (jk == Ijk_Boring || jk == Ijk_Call) { 4775663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng /* Boring transfer to known address */ 4776663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng AMD64AMode* amRIP = AMD64AMode_IR(offsIP, hregAMD64_RBP()); 4777663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng if (env->chainingAllowed) { 4778663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng /* .. almost always true .. */ 4779663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng /* Skip the event check at the dst if this is a forwards 4780663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng edge. */ 4781663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng Bool toFastEP 4782663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng = ((Addr64)cdst->Ico.U64) > env->max_ga; 4783663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng if (0) vex_printf("%s", toFastEP ? "X" : "."); 4784663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng addInstr(env, AMD64Instr_XDirect(cdst->Ico.U64, 4785663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng amRIP, Acc_ALWAYS, 4786663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng toFastEP)); 4787663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng } else { 4788663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng /* .. very occasionally .. */ 4789663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng /* We can't use chaining, so ask for an indirect transfer, 4790663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng as that's the cheapest alternative that is 4791663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng allowable. */ 4792663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng HReg r = iselIntExpr_R(env, next); 4793663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng addInstr(env, AMD64Instr_XAssisted(r, amRIP, Acc_ALWAYS, 4794663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng Ijk_Boring)); 4795663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng } 4796663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng return; 4797663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng } 4798663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng } 4799663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 4800663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng /* Case: call/return (==boring) transfer to any address */ 4801663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng switch (jk) { 4802663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng case Ijk_Boring: case Ijk_Ret: case Ijk_Call: { 4803663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng HReg r = iselIntExpr_R(env, next); 4804663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng AMD64AMode* amRIP = AMD64AMode_IR(offsIP, hregAMD64_RBP()); 4805663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng if (env->chainingAllowed) { 4806663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng addInstr(env, AMD64Instr_XIndir(r, amRIP, Acc_ALWAYS)); 4807663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng } else { 4808663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng addInstr(env, AMD64Instr_XAssisted(r, amRIP, Acc_ALWAYS, 4809663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng Ijk_Boring)); 4810663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng } 4811663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng return; 4812663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng } 4813663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng default: 4814663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng break; 4815663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng } 4816663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 4817663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng /* Case: assisted transfer to arbitrary address */ 4818663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng switch (jk) { 4819663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng /* Keep this list in sync with that for Ist_Exit above */ 4820663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng case Ijk_ClientReq: 4821663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng case Ijk_EmWarn: 4822663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng case Ijk_NoDecode: 4823663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng case Ijk_NoRedir: 4824663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng case Ijk_SigSEGV: 4825663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng case Ijk_SigTRAP: 4826663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng case Ijk_Sys_syscall: 4827eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov case Ijk_InvalICache: 4828663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng case Ijk_Yield: { 4829663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng HReg r = iselIntExpr_R(env, next); 4830663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng AMD64AMode* amRIP = AMD64AMode_IR(offsIP, hregAMD64_RBP()); 4831663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng addInstr(env, AMD64Instr_XAssisted(r, amRIP, Acc_ALWAYS, jk)); 4832663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng return; 4833663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng } 4834663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng default: 4835663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng break; 4836663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng } 4837663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 4838663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng vex_printf( "\n-- PUT(%d) = ", offsIP); 4839663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng ppIRExpr( next ); 4840663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng vex_printf( "; exit-"); 4841663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng ppIRJumpKind(jk); 4842663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng vex_printf( "\n"); 4843663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng vassert(0); // are we expecting any other kind? 4844ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 4845ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 4846ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 4847ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------*/ 4848ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Insn selector top-level ---*/ 4849ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------*/ 4850ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 4851ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Translate an entire SB to amd64 code. */ 4852ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 4853663860b1408516d02ebfcb3a9999a134e6cfb223Ben ChengHInstrArray* iselSB_AMD64 ( IRSB* bb, 4854663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng VexArch arch_host, 4855663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng VexArchInfo* archinfo_host, 4856663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng VexAbiInfo* vbi/*UNUSED*/, 4857663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng Int offs_Host_EvC_Counter, 4858663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng Int offs_Host_EvC_FailAddr, 4859663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng Bool chainingAllowed, 4860663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng Bool addProfInc, 4861663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng Addr64 max_ga ) 4862ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 4863663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng Int i, j; 4864663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng HReg hreg, hregHI; 4865663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng ISelEnv* env; 4866663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng UInt hwcaps_host = archinfo_host->hwcaps; 4867663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng AMD64AMode *amCounter, *amFailAddr; 4868ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 4869ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* sanity ... */ 4870ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert(arch_host == VexArchAMD64); 4871ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert(0 == (hwcaps_host 4872ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown & ~(VEX_HWCAPS_AMD64_SSE3 4873ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown | VEX_HWCAPS_AMD64_CX16 4874663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng | VEX_HWCAPS_AMD64_LZCNT 4875436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov | VEX_HWCAPS_AMD64_AVX 4876436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov | VEX_HWCAPS_AMD64_RDTSCP 4877436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov | VEX_HWCAPS_AMD64_BMI 4878436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov | VEX_HWCAPS_AMD64_AVX2))); 4879ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 4880ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Make up an initial environment to use. */ 4881ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown env = LibVEX_Alloc(sizeof(ISelEnv)); 4882ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown env->vreg_ctr = 0; 4883ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 4884ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Set up output code array. */ 4885ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown env->code = newHInstrArray(); 4886ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 4887ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Copy BB's type env. */ 4888ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown env->type_env = bb->tyenv; 4889ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 4890ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Make up an IRTemp -> virtual HReg mapping. This doesn't 4891ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown change as we go along. */ 4892ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown env->n_vregmap = bb->tyenv->types_used; 4893ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown env->vregmap = LibVEX_Alloc(env->n_vregmap * sizeof(HReg)); 4894ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown env->vregmapHI = LibVEX_Alloc(env->n_vregmap * sizeof(HReg)); 4895ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 4896ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* and finally ... */ 4897663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng env->chainingAllowed = chainingAllowed; 4898663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng env->hwcaps = hwcaps_host; 4899663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng env->max_ga = max_ga; 4900ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 4901ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* For each IR temporary, allocate a suitably-kinded virtual 4902ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown register. */ 4903ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown j = 0; 4904ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (i = 0; i < env->n_vregmap; i++) { 4905ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown hregHI = hreg = INVALID_HREG; 4906ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (bb->tyenv->types[i]) { 4907ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Ity_I1: 4908663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng case Ity_I8: case Ity_I16: case Ity_I32: case Ity_I64: 4909663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng hreg = mkHReg(j++, HRcInt64, True); 4910663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng break; 4911663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng case Ity_I128: 4912663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng hreg = mkHReg(j++, HRcInt64, True); 4913663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng hregHI = mkHReg(j++, HRcInt64, True); 4914663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng break; 4915ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Ity_F32: 4916ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Ity_F64: 4917663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng case Ity_V128: 4918663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng hreg = mkHReg(j++, HRcVec128, True); 4919663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng break; 4920663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng case Ity_V256: 4921663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng hreg = mkHReg(j++, HRcVec128, True); 4922663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng hregHI = mkHReg(j++, HRcVec128, True); 4923663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng break; 4924663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng default: 4925663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng ppIRType(bb->tyenv->types[i]); 4926663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng vpanic("iselBB(amd64): IRTemp type"); 4927ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4928ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown env->vregmap[i] = hreg; 4929ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown env->vregmapHI[i] = hregHI; 4930ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4931ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown env->vreg_ctr = j; 4932ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 4933663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng /* The very first instruction must be an event check. */ 4934663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng amCounter = AMD64AMode_IR(offs_Host_EvC_Counter, hregAMD64_RBP()); 4935663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng amFailAddr = AMD64AMode_IR(offs_Host_EvC_FailAddr, hregAMD64_RBP()); 4936663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng addInstr(env, AMD64Instr_EvCheck(amCounter, amFailAddr)); 4937663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 4938663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng /* Possibly a block counter increment (for profiling). At this 4939663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng point we don't know the address of the counter, so just pretend 4940663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng it is zero. It will have to be patched later, but before this 4941663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng translation is used, by a call to LibVEX_patchProfCtr. */ 4942663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng if (addProfInc) { 4943663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng addInstr(env, AMD64Instr_ProfInc()); 4944663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng } 4945663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 4946ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Ok, finally we can iterate over the statements. */ 4947ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (i = 0; i < bb->stmts_used; i++) 4948ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (bb->stmts[i]) 4949663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng iselStmt(env, bb->stmts[i]); 4950ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 4951663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng iselNext(env, bb->next, bb->jumpkind, bb->offsIP); 4952ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 4953ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* record the number of vregs we used. */ 4954ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown env->code->n_vregs = env->vreg_ctr; 4955ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return env->code; 4956ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 4957ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 4958ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 4959ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------------*/ 4960ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- end host_amd64_isel.c ---*/ 4961ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------------*/ 4962