1ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------------*/ 3ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- begin host_arm_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 NEON support is 14436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov Copyright (C) 2010-2013 Samsung Electronics 15ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown contributed by Dmitry Zhurikhin <zhur@ispras.ru> 16ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown and Kirill Batuzov <batuzovk@ispras.ru> 17ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 18ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown This program is free software; you can redistribute it and/or 19ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown modify it under the terms of the GNU General Public License as 20ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown published by the Free Software Foundation; either version 2 of the 21ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown License, or (at your option) any later version. 22ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 23ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown This program is distributed in the hope that it will be useful, but 24ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown WITHOUT ANY WARRANTY; without even the implied warranty of 25ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 26ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown General Public License for more details. 27ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 28ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown You should have received a copy of the GNU General Public License 29ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown along with this program; if not, write to the Free Software 30ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 31ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 02110-1301, USA. 32ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 33ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown The GNU General Public License is contained in the file COPYING. 34ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/ 35ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 36ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "libvex_basictypes.h" 37ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "libvex_ir.h" 38ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "libvex.h" 39ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "ir_match.h" 40ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 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" // for 32-bit SIMD helpers 45ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "host_arm_defs.h" 46ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 47ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 48ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------*/ 49ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- ARMvfp control word stuff ---*/ 50ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------*/ 51ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 52ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Vex-generated code expects to run with the FPU set as follows: all 53ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown exceptions masked, round-to-nearest, non-vector mode, with the NZCV 54ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown flags cleared, and FZ (flush to zero) disabled. Curiously enough, 55ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown this corresponds to a FPSCR value of zero. 56ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 57ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fpscr should therefore be zero on entry to Vex-generated code, and 58ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown should be unchanged at exit. (Or at least the bottom 28 bits 59ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown should be zero). 60ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/ 61ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 62ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define DEFAULT_FPSCR 0 63ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 64ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 65ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------*/ 66ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- ISelEnv ---*/ 67ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------*/ 68ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 69ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* This carries around: 70ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 71ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown - A mapping from IRTemp to IRType, giving the type of any IRTemp we 72ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown might encounter. This is computed before insn selection starts, 73ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown and does not change. 74ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 75ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown - A mapping from IRTemp to HReg. This tells the insn selector 76ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown which virtual register(s) are associated with each IRTemp 77ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown temporary. This is computed before insn selection starts, and 78ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown does not change. We expect this mapping to map precisely the 79ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown same set of IRTemps as the type mapping does. 80ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 81ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown - vregmap holds the primary register for the IRTemp. 82ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown - vregmapHI is only used for 64-bit integer-typed 83ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRTemps. It holds the identity of a second 84ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 32-bit virtual HReg, which holds the high half 85ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown of the value. 86ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 87ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown - The code array, that is, the insns selected so far. 88ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 89ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown - A counter, for generating new virtual registers. 90ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 91ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown - The host hardware capabilities word. This is set at the start 92ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown and does not change. 93ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 94663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng - A Bool for indicating whether we may generate chain-me 95663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng instructions for control flow transfers, or whether we must use 96663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng XAssisted. 97663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 98663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng - The maximum guest address of any guest insn in this block. 99663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng Actually, the address of the highest-addressed byte from any insn 100663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng in this block. Is set at the start and does not change. This is 101663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng used for detecting jumps which are definitely forward-edges from 102663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng this block, and therefore can be made (chained) to the fast entry 103663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng point of the destination, thereby avoiding the destination's 104663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng event check. 105663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 106663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng Note, this is all (well, mostly) host-independent. 107663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng*/ 108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef 110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown struct { 111663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng /* Constant -- are set at the start and do not change. */ 112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRTypeEnv* type_env; 113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg* vregmap; 115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg* vregmapHI; 116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int n_vregmap; 117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 118663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng UInt hwcaps; 119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 120663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng Bool chainingAllowed; 121663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng Addr64 max_ga; 122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 123663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng /* These are modified as we go along. */ 124663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng HInstrArray* code; 125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int vreg_ctr; 126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ISelEnv; 128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic HReg lookupIRTemp ( ISelEnv* env, IRTemp tmp ) 130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert(tmp >= 0); 132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert(tmp < env->n_vregmap); 133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return env->vregmap[tmp]; 134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void lookupIRTemp64 ( HReg* vrHI, HReg* vrLO, ISelEnv* env, IRTemp tmp ) 137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert(tmp >= 0); 139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert(tmp < env->n_vregmap); 140436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov vassert(! hregIsInvalid(env->vregmapHI[tmp])); 141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *vrLO = env->vregmap[tmp]; 142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *vrHI = env->vregmapHI[tmp]; 143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void addInstr ( ISelEnv* env, ARMInstr* instr ) 146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addHInstr(env->code, instr); 148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (vex_traceflags & VEX_TRACE_VCODE) { 149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ppARMInstr(instr); 150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vex_printf("\n"); 151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if 0 153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (instr->tag == ARMin_NUnary || instr->tag == ARMin_NBinary 154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown || instr->tag == ARMin_NUnaryS || instr->tag == ARMin_NBinaryS 155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown || instr->tag == ARMin_NDual || instr->tag == ARMin_NShift) { 156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ppARMInstr(instr); 157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vex_printf("\n"); 158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif 160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic HReg newVRegI ( ISelEnv* env ) 163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg reg = mkHReg(env->vreg_ctr, HRcInt32, True/*virtual reg*/); 165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown env->vreg_ctr++; 166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return reg; 167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic HReg newVRegD ( ISelEnv* env ) 170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg reg = mkHReg(env->vreg_ctr, HRcFlt64, True/*virtual reg*/); 172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown env->vreg_ctr++; 173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return reg; 174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic HReg newVRegF ( ISelEnv* env ) 177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg reg = mkHReg(env->vreg_ctr, HRcFlt32, True/*virtual reg*/); 179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown env->vreg_ctr++; 180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return reg; 181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic HReg newVRegV ( ISelEnv* env ) 184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg reg = mkHReg(env->vreg_ctr, HRcVec128, True/*virtual reg*/); 186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown env->vreg_ctr++; 187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return reg; 188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* These are duplicated in guest_arm_toIR.c */ 191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRExpr* unop ( IROp op, IRExpr* a ) 192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return IRExpr_Unop(op, a); 194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRExpr* binop ( IROp op, IRExpr* a1, IRExpr* a2 ) 197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return IRExpr_Binop(op, a1, a2); 199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRExpr* bind ( Int binder ) 202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return IRExpr_Binder(binder); 204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------*/ 208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- ISEL: Forward declarations ---*/ 209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------*/ 210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* These are organised as iselXXX and iselXXX_wrk pairs. The 212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown iselXXX_wrk do the real work, but are not to be called directly. 213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown For each XXX, iselXXX calls its iselXXX_wrk counterpart, then 214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown checks that all returned registers are virtual. You should not 215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown call the _wrk version directly. 216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/ 217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic ARMAMode1* iselIntExpr_AMode1_wrk ( ISelEnv* env, IRExpr* e ); 218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic ARMAMode1* iselIntExpr_AMode1 ( ISelEnv* env, IRExpr* e ); 219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic ARMAMode2* iselIntExpr_AMode2_wrk ( ISelEnv* env, IRExpr* e ); 221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic ARMAMode2* iselIntExpr_AMode2 ( ISelEnv* env, IRExpr* e ); 222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic ARMAModeV* iselIntExpr_AModeV_wrk ( ISelEnv* env, IRExpr* e ); 224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic ARMAModeV* iselIntExpr_AModeV ( ISelEnv* env, IRExpr* e ); 225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 226b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic ARMAModeN* iselIntExpr_AModeN_wrk ( ISelEnv* env, IRExpr* e ); 227b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic ARMAModeN* iselIntExpr_AModeN ( ISelEnv* env, IRExpr* e ); 228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic ARMRI84* iselIntExpr_RI84_wrk 230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ( /*OUT*/Bool* didInv, Bool mayInv, ISelEnv* env, IRExpr* e ); 231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic ARMRI84* iselIntExpr_RI84 232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ( /*OUT*/Bool* didInv, Bool mayInv, ISelEnv* env, IRExpr* e ); 233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic ARMRI5* iselIntExpr_RI5_wrk ( ISelEnv* env, IRExpr* e ); 235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic ARMRI5* iselIntExpr_RI5 ( ISelEnv* env, IRExpr* e ); 236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic ARMCondCode iselCondCode_wrk ( ISelEnv* env, IRExpr* e ); 238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic ARMCondCode iselCondCode ( ISelEnv* env, IRExpr* e ); 239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic HReg iselIntExpr_R_wrk ( ISelEnv* env, IRExpr* e ); 241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic HReg iselIntExpr_R ( ISelEnv* env, IRExpr* e ); 242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void iselInt64Expr_wrk ( HReg* rHi, HReg* rLo, 244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ISelEnv* env, IRExpr* e ); 245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void iselInt64Expr ( HReg* rHi, HReg* rLo, 246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ISelEnv* env, IRExpr* e ); 247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic HReg iselDblExpr_wrk ( ISelEnv* env, IRExpr* e ); 249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic HReg iselDblExpr ( ISelEnv* env, IRExpr* e ); 250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic HReg iselFltExpr_wrk ( ISelEnv* env, IRExpr* e ); 252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic HReg iselFltExpr ( ISelEnv* env, IRExpr* e ); 253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic HReg iselNeon64Expr_wrk ( ISelEnv* env, IRExpr* e ); 255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic HReg iselNeon64Expr ( ISelEnv* env, IRExpr* e ); 256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic HReg iselNeonExpr_wrk ( ISelEnv* env, IRExpr* e ); 258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic HReg iselNeonExpr ( ISelEnv* env, IRExpr* e ); 259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------*/ 261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- ISEL: Misc helpers ---*/ 262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------*/ 263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic UInt ROR32 ( UInt x, UInt sh ) { 265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert(sh >= 0 && sh < 32); 266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (sh == 0) 267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return x; 268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown else 269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return (x << (32-sh)) | (x >> sh); 270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Figure out if 'u' fits in the special shifter-operand 8x4 immediate 273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown form, and if so return the components. */ 274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool fitsIn8x4 ( /*OUT*/UInt* u8, /*OUT*/UInt* u4, UInt u ) 275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt i; 277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (i = 0; i < 16; i++) { 278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (0 == (u & 0xFFFFFF00)) { 279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *u8 = u; 280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *u4 = i; 281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return True; 282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown u = ROR32(u, 30); 284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert(i == 16); 286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return False; 287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Make a int reg-reg move. */ 290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic ARMInstr* mk_iMOVds_RR ( HReg dst, HReg src ) 291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert(hregClass(src) == HRcInt32); 293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert(hregClass(dst) == HRcInt32); 294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return ARMInstr_Mov(dst, ARMRI84_R(src)); 295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Set the VFP unit's rounding mode to default (round to nearest). */ 298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void set_VFP_rounding_default ( ISelEnv* env ) 299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* mov rTmp, #DEFAULT_FPSCR 301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fmxr fpscr, rTmp 302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */ 303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg rTmp = newVRegI(env); 304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_Imm32(rTmp, DEFAULT_FPSCR)); 305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_FPSCR(True/*toFPSCR*/, rTmp)); 306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Mess with the VFP unit's rounding mode: 'mode' is an I32-typed 309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown expression denoting a value in the range 0 .. 3, indicating a round 310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mode encoded as per type IRRoundingMode. Set FPSCR to have the 311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown same rounding. 312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/ 313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic 314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid set_VFP_rounding_mode ( ISelEnv* env, IRExpr* mode ) 315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* This isn't simple, because 'mode' carries an IR rounding 317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown encoding, and we need to translate that to an ARMvfp one: 318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown The IR encoding: 319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 00 to nearest (the default) 320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 10 to +infinity 321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 01 to -infinity 322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 11 to zero 323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown The ARMvfp encoding: 324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 00 to nearest 325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 01 to +infinity 326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 10 to -infinity 327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 11 to zero 328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Easy enough to do; just swap the two bits. 329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */ 330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg irrm = iselIntExpr_R(env, mode); 331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg tL = newVRegI(env); 332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg tR = newVRegI(env); 333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg t3 = newVRegI(env); 334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* tL = irrm << 1; 335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tR = irrm >> 1; if we're lucky, these will issue together 336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tL &= 2; 337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tR &= 1; ditto 338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown t3 = tL | tR; 339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown t3 <<= 22; 340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fmxr fpscr, t3 341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */ 342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_Shift(ARMsh_SHL, tL, irrm, ARMRI5_I5(1))); 343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_Shift(ARMsh_SHR, tR, irrm, ARMRI5_I5(1))); 344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_Alu(ARMalu_AND, tL, tL, ARMRI84_I84(2,0))); 345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_Alu(ARMalu_AND, tR, tR, ARMRI84_I84(1,0))); 346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_Alu(ARMalu_OR, t3, tL, ARMRI84_R(tR))); 347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_Shift(ARMsh_SHL, t3, t3, ARMRI5_I5(22))); 348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_FPSCR(True/*toFPSCR*/, t3)); 349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------*/ 353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- ISEL: Function call helpers ---*/ 354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------*/ 355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Used only in doHelperCall. See big comment in doHelperCall re 357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown handling of register-parameter args. This function figures out 358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown whether evaluation of an expression might require use of a fixed 359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown register. If in doubt return True (safe but suboptimal). 360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/ 361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic 362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownBool mightRequireFixedRegs ( IRExpr* e ) 363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 364436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov if (UNLIKELY(is_IRExpr_VECRET_or_BBPTR(e))) { 365436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov // These are always "safe" -- either a copy of r13(sp) in some 366436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov // arbitrary vreg, or a copy of r8, respectively. 367436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov return False; 368436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } 369436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /* Else it's a "normal" expression. */ 370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (e->tag) { 371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iex_RdTmp: case Iex_Const: case Iex_Get: 372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return False; 373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: 374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return True; 375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 379436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov/* Do a complete function call. |guard| is a Ity_Bit expression 380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown indicating whether or not the call happens. If guard==NULL, the 381436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov call is unconditional. |retloc| is set to indicate where the 382436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov return value is after the call. The caller (of this fn) must 383436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov generate code to add |stackAdjustAfterCall| to the stack pointer 384436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov after the call is done. Returns True iff it managed to handle this 385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown combination of arg/return types, else returns False. */ 386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic 388436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy IvanovBool doHelperCall ( /*OUT*/UInt* stackAdjustAfterCall, 389436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /*OUT*/RetLoc* retloc, 390436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov ISelEnv* env, 391436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov IRExpr* guard, 392436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov IRCallee* cee, IRType retTy, IRExpr** args ) 393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ARMCondCode cc; 395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argregs[ARM_N_ARGREGS]; 396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg tmpregs[ARM_N_ARGREGS]; 397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bool go_fast; 398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int n_args, i, nextArgReg; 399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ULong target; 400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert(ARM_N_ARGREGS == 4); 402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 403436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /* Set default returns. We'll update them later if needed. */ 404436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov *stackAdjustAfterCall = 0; 405436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov *retloc = mk_RetLoc_INVALID(); 406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 407436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /* These are used for cross-checking that IR-level constraints on 408436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov the use of IRExpr_VECRET() and IRExpr_BBPTR() are observed. */ 409436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov UInt nVECRETs = 0; 410436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov UInt nBBPTRs = 0; 411436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 412436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /* Marshal args for a call and do the call. 413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown This function only deals with a tiny set of possibilities, which 415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown cover all helpers in practice. The restrictions are that only 416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown arguments in registers are supported, hence only ARM_N_REGPARMS 417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown x 32 integer bits in total can be passed. In fact the only 418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown supported arg types are I32 and I64. 419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 420436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov The return type can be I{64,32} or V128. In the V128 case, it 421436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov is expected that |args| will contain the special node 422436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov IRExpr_VECRET(), in which case this routine generates code to 423436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov allocate space on the stack for the vector return value. Since 424436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov we are not passing any scalars on the stack, it is enough to 425436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov preallocate the return space before marshalling any arguments, 426436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov in this case. 427436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 428436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov |args| may also contain IRExpr_BBPTR(), in which case the 429436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov value in r8 is passed as the corresponding argument. 430436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Generating code which is both efficient and correct when 432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown parameters are to be passed in registers is difficult, for the 433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown reasons elaborated in detail in comments attached to 434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown doHelperCall() in priv/host-x86/isel.c. Here, we use a variant 435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown of the method described in those comments. 436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown The problem is split into two cases: the fast scheme and the 438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown slow scheme. In the fast scheme, arguments are computed 439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown directly into the target (real) registers. This is only safe 440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown when we can be sure that computation of each argument will not 441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown trash any real registers set by computation of any other 442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown argument. 443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown In the slow scheme, all args are first computed into vregs, and 445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown once they are all done, they are moved to the relevant real 446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown regs. This always gives correct code, but it also gives a bunch 447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown of vreg-to-rreg moves which are usually redundant but are hard 448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for the register allocator to get rid of. 449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown To decide which scheme to use, all argument expressions are 451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown first examined. If they are all so simple that it is clear they 452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown will be evaluated without use of any fixed registers, use the 453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fast scheme, else use the slow scheme. Note also that only 454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown unconditional calls may use the fast scheme, since having to 455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown compute a condition expression could itself trash real 456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown registers. 457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Note this requires being able to examine an expression and 459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown determine whether or not evaluation of it might use a fixed 460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown register. That requires knowledge of how the rest of this insn 461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown selector works. Currently just the following 3 are regarded as 462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown safe -- hopefully they cover the majority of arguments in 463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown practice: IRExpr_Tmp IRExpr_Const IRExpr_Get. 464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */ 465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Note that the cee->regparms field is meaningless on ARM hosts 467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (since there is only one calling convention) and so we always 468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ignore it. */ 469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown n_args = 0; 471436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov for (i = 0; args[i]; i++) { 472436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov IRExpr* arg = args[i]; 473436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov if (UNLIKELY(arg->tag == Iex_VECRET)) { 474436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov nVECRETs++; 475436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } else if (UNLIKELY(arg->tag == Iex_BBPTR)) { 476436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov nBBPTRs++; 477436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } 478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown n_args++; 479436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } 480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown argregs[0] = hregARM_R0(); 482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown argregs[1] = hregARM_R1(); 483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown argregs[2] = hregARM_R2(); 484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown argregs[3] = hregARM_R3(); 485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tmpregs[0] = tmpregs[1] = tmpregs[2] = 487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tmpregs[3] = INVALID_HREG; 488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* First decide which scheme (slow or fast) is to be used. First 490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown assume the fast scheme, and select slow if any contraindications 491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (wow) appear. */ 492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown go_fast = True; 494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (guard) { 496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (guard->tag == Iex_Const 497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && guard->Iex.Const.con->tag == Ico_U1 498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && guard->Iex.Const.con->Ico.U1 == True) { 499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* unconditional */ 500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Not manifestly unconditional -- be conservative. */ 502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown go_fast = False; 503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 506ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (go_fast) { 507ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (i = 0; i < n_args; i++) { 508ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (mightRequireFixedRegs(args[i])) { 509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown go_fast = False; 510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 511ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 512ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 513ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 514436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 515436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov if (go_fast) { 516436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov if (retTy == Ity_V128 || retTy == Ity_V256) 517436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov go_fast = False; 518436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } 519436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* At this point the scheme to use has been established. Generate 521ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown code to get the arg values into the argument rregs. If we run 522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown out of arg regs, give up. */ 523ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 524ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (go_fast) { 525ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 526ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* FAST SCHEME */ 527ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown nextArgReg = 0; 528ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 529ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (i = 0; i < n_args; i++) { 530436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov IRExpr* arg = args[i]; 531436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 532436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov IRType aTy = Ity_INVALID; 533436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov if (LIKELY(!is_IRExpr_VECRET_or_BBPTR(arg))) 534436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov aTy = typeOfIRExpr(env->type_env, arg); 535436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 536ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (nextArgReg >= ARM_N_ARGREGS) 537ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return False; /* out of argregs */ 538436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 539ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (aTy == Ity_I32) { 540ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, mk_iMOVds_RR( argregs[nextArgReg], 541436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov iselIntExpr_R(env, arg) )); 542ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown nextArgReg++; 543ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 544ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown else if (aTy == Ity_I64) { 545ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* 64-bit args must be passed in an a reg-pair of the form 546ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown n:n+1, where n is even. Hence either r0:r1 or r2:r3. 547ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown On a little-endian host, the less significant word is 548ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown passed in the lower-numbered register. */ 549ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (nextArgReg & 1) { 550ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (nextArgReg >= ARM_N_ARGREGS) 551ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return False; /* out of argregs */ 552ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_Imm32( argregs[nextArgReg], 0xAA )); 553ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown nextArgReg++; 554ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (nextArgReg >= ARM_N_ARGREGS) 556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return False; /* out of argregs */ 557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg raHi, raLo; 558436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov iselInt64Expr(&raHi, &raLo, env, arg); 559ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, mk_iMOVds_RR( argregs[nextArgReg], raLo )); 560ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown nextArgReg++; 561ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, mk_iMOVds_RR( argregs[nextArgReg], raHi )); 562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown nextArgReg++; 563ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 564436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov else if (arg->tag == Iex_BBPTR) { 565436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov vassert(0); //ATC 566436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov addInstr(env, mk_iMOVds_RR( argregs[nextArgReg], 567436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov hregARM_R8() )); 568436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov nextArgReg++; 569436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } 570436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov else if (arg->tag == Iex_VECRET) { 571436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov // If this happens, it denotes ill-formed IR 572436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov vassert(0); 573436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } 574ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown else 575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return False; /* unhandled arg type */ 576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Fast scheme only applies for unconditional calls. Hence: */ 579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown cc = ARMcc_AL; 580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 581ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 582ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* SLOW SCHEME; move via temporaries */ 584ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown nextArgReg = 0; 585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 586ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (i = 0; i < n_args; i++) { 587436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov IRExpr* arg = args[i]; 588436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 589436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov IRType aTy = Ity_INVALID; 590436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov if (LIKELY(!is_IRExpr_VECRET_or_BBPTR(arg))) 591436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov aTy = typeOfIRExpr(env->type_env, arg); 592436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (nextArgReg >= ARM_N_ARGREGS) 594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return False; /* out of argregs */ 595436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (aTy == Ity_I32) { 597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tmpregs[nextArgReg] = iselIntExpr_R(env, args[i]); 598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown nextArgReg++; 599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown else if (aTy == Ity_I64) { 601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Same comment applies as in the Fast-scheme case. */ 602ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (nextArgReg & 1) 603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown nextArgReg++; 604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (nextArgReg + 1 >= ARM_N_ARGREGS) 605ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return False; /* out of argregs */ 606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg raHi, raLo; 607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown iselInt64Expr(&raHi, &raLo, env, args[i]); 608ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tmpregs[nextArgReg] = raLo; 609ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown nextArgReg++; 610ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tmpregs[nextArgReg] = raHi; 611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown nextArgReg++; 612ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 613436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov else if (arg->tag == Iex_BBPTR) { 614436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov vassert(0); //ATC 615436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov tmpregs[nextArgReg] = hregARM_R8(); 616436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov nextArgReg++; 617436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } 618436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov else if (arg->tag == Iex_VECRET) { 619436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov // If this happens, it denotes ill-formed IR 620436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov vassert(0); 621436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } 622436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov else 623436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov return False; /* unhandled arg type */ 624ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 625ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 626ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Now we can compute the condition. We can't do it earlier 627ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown because the argument computations could trash the condition 628ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown codes. Be a bit clever to handle the common case where the 629ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown guard is 1:Bit. */ 630ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown cc = ARMcc_AL; 631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (guard) { 632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (guard->tag == Iex_Const 633ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && guard->Iex.Const.con->tag == Ico_U1 634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && guard->Iex.Const.con->Ico.U1 == True) { 635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* unconditional -- do nothing */ 636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown cc = iselCondCode( env, guard ); 638ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 639ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 640ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 641ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Move the args to their final destinations. */ 642ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (i = 0; i < nextArgReg; i++) { 643436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov if (hregIsInvalid(tmpregs[i])) { // Skip invalid regs 644ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_Imm32( argregs[i], 0xAA )); 645ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown continue; 646ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 647ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* None of these insns, including any spill code that might 648ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown be generated, may alter the condition codes. */ 649ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr( env, mk_iMOVds_RR( argregs[i], tmpregs[i] ) ); 650ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 652ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 653ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 654ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Should be assured by checks above */ 655ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert(nextArgReg <= ARM_N_ARGREGS); 656ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 657436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /* Do final checks, set the return values, and generate the call 658436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov instruction proper. */ 659436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov vassert(nBBPTRs == 0 || nBBPTRs == 1); 660436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov vassert(nVECRETs == (retTy == Ity_V128 || retTy == Ity_V256) ? 1 : 0); 661436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov vassert(*stackAdjustAfterCall == 0); 662436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov vassert(is_RetLoc_INVALID(*retloc)); 663436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov switch (retTy) { 664436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case Ity_INVALID: 665436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /* Function doesn't return a value. */ 666436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov *retloc = mk_RetLoc_simple(RLPri_None); 667436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov break; 668436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case Ity_I64: 669436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov *retloc = mk_RetLoc_simple(RLPri_2Int); 670436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov break; 671436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case Ity_I32: case Ity_I16: case Ity_I8: 672436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov *retloc = mk_RetLoc_simple(RLPri_Int); 673436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov break; 674436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case Ity_V128: 675436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov vassert(0); // ATC 676436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov *retloc = mk_RetLoc_spRel(RLPri_V128SpRel, 0); 677436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov *stackAdjustAfterCall = 16; 678436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov break; 679436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case Ity_V256: 680436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov vassert(0); // ATC 681436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov *retloc = mk_RetLoc_spRel(RLPri_V256SpRel, 0); 682436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov *stackAdjustAfterCall = 32; 683436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov break; 684436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov default: 685436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /* IR can denote other possible return types, but we don't 686436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov handle those here. */ 687436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov vassert(0); 688436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } 689436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 690436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /* Finally, generate the call itself. This needs the *retloc value 691436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov set in the switch above, which is why it's at the end. */ 692ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 693ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* nextArgReg doles out argument registers. Since these are 694ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown assigned in the order r0, r1, r2, r3, its numeric value at this 695ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown point, which must be between 0 and 4 inclusive, is going to be 696ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown equal to the number of arg regs in use for the call. Hence bake 697ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown that number into the call (we'll need to know it when doing 698ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown register allocation, to know what regs the call reads.) 699ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 700ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown There is a bit of a twist -- harmless but worth recording. 701ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Suppose the arg types are (Ity_I32, Ity_I64). Then we will have 702ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown the first arg in r0 and the second in r3:r2, but r1 isn't used. 703ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown We nevertheless have nextArgReg==4 and bake that into the call 704ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown instruction. This will mean the register allocator wil believe 705ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown this insn reads r1 when in fact it doesn't. But that's 706ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown harmless; it just artificially extends the live range of r1 707ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown unnecessarily. The best fix would be to put into the 708ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown instruction, a bitmask indicating which of r0/1/2/3 carry live 709ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown values. But that's too much hassle. */ 710ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 711436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov target = (HWord)Ptr_to_ULong(cee->addr); 712436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov addInstr(env, ARMInstr_Call( cc, target, nextArgReg, *retloc )); 713ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 714ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return True; /* success */ 715ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 716ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 717ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 718ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------*/ 719ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- ISEL: Integer expressions (32/16/8 bit) ---*/ 720ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------*/ 721ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 722ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Select insns for an integer-typed expression, and add them to the 723ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown code list. Return a reg holding the result. This reg will be a 724ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown virtual register. THE RETURNED REG MUST NOT BE MODIFIED. If you 725ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown want to modify it, ask for a new vreg, copy it in there, and modify 726ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown the copy. The register allocator will do its best to map both 727ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vregs to the same real register, so the copies will often disappear 728ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown later in the game. 729ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 730ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown This should handle expressions of 32, 16 and 8-bit type. All 731ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown results are returned in a 32-bit register. For 16- and 8-bit 732ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown expressions, the upper 16/24 bits are arbitrary, so you should mask 733ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown or sign extend partial values if necessary. 734ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/ 735ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 736ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* --------------------- AMode1 --------------------- */ 737ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 738ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Return an AMode1 which computes the value of the specified 739ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown expression, possibly also adding insns to the code list as a 740ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown result. The expression may only be a 32-bit one. 741ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/ 742ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 743ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool sane_AMode1 ( ARMAMode1* am ) 744ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 745ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (am->tag) { 746ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case ARMam1_RI: 747ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return 748ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown toBool( hregClass(am->ARMam1.RI.reg) == HRcInt32 749ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && (hregIsVirtual(am->ARMam1.RI.reg) 750436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov || sameHReg(am->ARMam1.RI.reg, hregARM_R8())) 751ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && am->ARMam1.RI.simm13 >= -4095 752ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && am->ARMam1.RI.simm13 <= 4095 ); 753ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case ARMam1_RRS: 754ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return 755ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown toBool( hregClass(am->ARMam1.RRS.base) == HRcInt32 756ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && hregIsVirtual(am->ARMam1.RRS.base) 757ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && hregClass(am->ARMam1.RRS.index) == HRcInt32 758ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && hregIsVirtual(am->ARMam1.RRS.index) 759ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && am->ARMam1.RRS.shift >= 0 760ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && am->ARMam1.RRS.shift <= 3 ); 761ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: 762ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vpanic("sane_AMode: unknown ARM AMode1 tag"); 763ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 764ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 765ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 766ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic ARMAMode1* iselIntExpr_AMode1 ( ISelEnv* env, IRExpr* e ) 767ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 768ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ARMAMode1* am = iselIntExpr_AMode1_wrk(env, e); 769ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert(sane_AMode1(am)); 770ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return am; 771ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 772ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 773ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic ARMAMode1* iselIntExpr_AMode1_wrk ( ISelEnv* env, IRExpr* e ) 774ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 775ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRType ty = typeOfIRExpr(env->type_env,e); 776ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert(ty == Ity_I32); 777ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 778ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* FIXME: add RRS matching */ 779ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 780ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* {Add32,Sub32}(expr,simm13) */ 781ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->tag == Iex_Binop 782ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && (e->Iex.Binop.op == Iop_Add32 || e->Iex.Binop.op == Iop_Sub32) 783ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && e->Iex.Binop.arg2->tag == Iex_Const 784ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && e->Iex.Binop.arg2->Iex.Const.con->tag == Ico_U32) { 785ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int simm = (Int)e->Iex.Binop.arg2->Iex.Const.con->Ico.U32; 786ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (simm >= -4095 && simm <= 4095) { 787ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg reg; 788ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->Iex.Binop.op == Iop_Sub32) 789ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown simm = -simm; 790ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown reg = iselIntExpr_R(env, e->Iex.Binop.arg1); 791ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return ARMAMode1_RI(reg, simm); 792ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 793ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 794ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 795ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Doesn't match anything in particular. Generate it into 796ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown a register and use that. */ 797ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown { 798ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg reg = iselIntExpr_R(env, e); 799ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return ARMAMode1_RI(reg, 0); 800ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 801ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 802ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 803ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 804ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 805ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* --------------------- AMode2 --------------------- */ 806ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 807ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Return an AMode2 which computes the value of the specified 808ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown expression, possibly also adding insns to the code list as a 809ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown result. The expression may only be a 32-bit one. 810ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/ 811ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 812ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool sane_AMode2 ( ARMAMode2* am ) 813ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 814ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (am->tag) { 815ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case ARMam2_RI: 816ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return 817ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown toBool( hregClass(am->ARMam2.RI.reg) == HRcInt32 818ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && hregIsVirtual(am->ARMam2.RI.reg) 819ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && am->ARMam2.RI.simm9 >= -255 820ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && am->ARMam2.RI.simm9 <= 255 ); 821ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case ARMam2_RR: 822ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return 823ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown toBool( hregClass(am->ARMam2.RR.base) == HRcInt32 824ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && hregIsVirtual(am->ARMam2.RR.base) 825ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && hregClass(am->ARMam2.RR.index) == HRcInt32 826ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && hregIsVirtual(am->ARMam2.RR.index) ); 827ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: 828ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vpanic("sane_AMode: unknown ARM AMode2 tag"); 829ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 830ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 831ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 832ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic ARMAMode2* iselIntExpr_AMode2 ( ISelEnv* env, IRExpr* e ) 833ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 834ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ARMAMode2* am = iselIntExpr_AMode2_wrk(env, e); 835ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert(sane_AMode2(am)); 836ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return am; 837ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 838ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 839ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic ARMAMode2* iselIntExpr_AMode2_wrk ( ISelEnv* env, IRExpr* e ) 840ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 841ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRType ty = typeOfIRExpr(env->type_env,e); 842ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert(ty == Ity_I32); 843ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 844ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* FIXME: add RR matching */ 845ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 846ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* {Add32,Sub32}(expr,simm8) */ 847ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->tag == Iex_Binop 848ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && (e->Iex.Binop.op == Iop_Add32 || e->Iex.Binop.op == Iop_Sub32) 849ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && e->Iex.Binop.arg2->tag == Iex_Const 850ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && e->Iex.Binop.arg2->Iex.Const.con->tag == Ico_U32) { 851ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int simm = (Int)e->Iex.Binop.arg2->Iex.Const.con->Ico.U32; 852ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (simm >= -255 && simm <= 255) { 853ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg reg; 854ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->Iex.Binop.op == Iop_Sub32) 855ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown simm = -simm; 856ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown reg = iselIntExpr_R(env, e->Iex.Binop.arg1); 857ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return ARMAMode2_RI(reg, simm); 858ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 859ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 860ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 861ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Doesn't match anything in particular. Generate it into 862ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown a register and use that. */ 863ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown { 864ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg reg = iselIntExpr_R(env, e); 865ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return ARMAMode2_RI(reg, 0); 866ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 867ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 868ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 869ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 870ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 871ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* --------------------- AModeV --------------------- */ 872ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 873ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Return an AModeV which computes the value of the specified 874ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown expression, possibly also adding insns to the code list as a 875ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown result. The expression may only be a 32-bit one. 876ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/ 877ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 878ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool sane_AModeV ( ARMAModeV* am ) 879ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 880ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return toBool( hregClass(am->reg) == HRcInt32 881ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && hregIsVirtual(am->reg) 882ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && am->simm11 >= -1020 && am->simm11 <= 1020 883ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && 0 == (am->simm11 & 3) ); 884ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 885ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 886ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic ARMAModeV* iselIntExpr_AModeV ( ISelEnv* env, IRExpr* e ) 887ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 888ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ARMAModeV* am = iselIntExpr_AModeV_wrk(env, e); 889ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert(sane_AModeV(am)); 890ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return am; 891ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 892ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 893ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic ARMAModeV* iselIntExpr_AModeV_wrk ( ISelEnv* env, IRExpr* e ) 894ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 895ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRType ty = typeOfIRExpr(env->type_env,e); 896ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert(ty == Ity_I32); 897ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 898ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* {Add32,Sub32}(expr, simm8 << 2) */ 899ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->tag == Iex_Binop 900ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && (e->Iex.Binop.op == Iop_Add32 || e->Iex.Binop.op == Iop_Sub32) 901ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && e->Iex.Binop.arg2->tag == Iex_Const 902ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && e->Iex.Binop.arg2->Iex.Const.con->tag == Ico_U32) { 903ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int simm = (Int)e->Iex.Binop.arg2->Iex.Const.con->Ico.U32; 904ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (simm >= -1020 && simm <= 1020 && 0 == (simm & 3)) { 905ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg reg; 906ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->Iex.Binop.op == Iop_Sub32) 907ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown simm = -simm; 908ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown reg = iselIntExpr_R(env, e->Iex.Binop.arg1); 909ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return mkARMAModeV(reg, simm); 910ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 911ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 912ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 913ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Doesn't match anything in particular. Generate it into 914ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown a register and use that. */ 915ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown { 916ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg reg = iselIntExpr_R(env, e); 917ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return mkARMAModeV(reg, 0); 918ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 919ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 920ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 921ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 922ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* -------------------- AModeN -------------------- */ 923ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 924ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic ARMAModeN* iselIntExpr_AModeN ( ISelEnv* env, IRExpr* e ) 925ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 926ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return iselIntExpr_AModeN_wrk(env, e); 927ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 928ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 929ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic ARMAModeN* iselIntExpr_AModeN_wrk ( ISelEnv* env, IRExpr* e ) 930ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 931ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg reg = iselIntExpr_R(env, e); 932ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return mkARMAModeN_R(reg); 933ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 934ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 935ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 936ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* --------------------- RI84 --------------------- */ 937ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 938ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Select instructions to generate 'e' into a RI84. If mayInv is 939ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown true, then the caller will also accept an I84 form that denotes 940ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 'not e'. In this case didInv may not be NULL, and *didInv is set 941ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown to True. This complication is so as to allow generation of an RI84 942ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown which is suitable for use in either an AND or BIC instruction, 943ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown without knowing (before this call) which one. 944ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/ 945ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic ARMRI84* iselIntExpr_RI84 ( /*OUT*/Bool* didInv, Bool mayInv, 946ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ISelEnv* env, IRExpr* e ) 947ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 948ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ARMRI84* ri; 949ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (mayInv) 950ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert(didInv != NULL); 951ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ri = iselIntExpr_RI84_wrk(didInv, mayInv, env, e); 952ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* sanity checks ... */ 953ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (ri->tag) { 954ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case ARMri84_I84: 955ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return ri; 956ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case ARMri84_R: 957ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert(hregClass(ri->ARMri84.R.reg) == HRcInt32); 958ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert(hregIsVirtual(ri->ARMri84.R.reg)); 959ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return ri; 960ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: 961ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vpanic("iselIntExpr_RI84: unknown arm RI84 tag"); 962ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 963ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 964ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 965ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* DO NOT CALL THIS DIRECTLY ! */ 966ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic ARMRI84* iselIntExpr_RI84_wrk ( /*OUT*/Bool* didInv, Bool mayInv, 967ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ISelEnv* env, IRExpr* e ) 968ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 969ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRType ty = typeOfIRExpr(env->type_env,e); 970ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert(ty == Ity_I32 || ty == Ity_I16 || ty == Ity_I8); 971ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 972ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (didInv) *didInv = False; 973ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 974ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* special case: immediate */ 975ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->tag == Iex_Const) { 976ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt u, u8 = 0x100, u4 = 0x10; /* both invalid */ 977ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (e->Iex.Const.con->tag) { 978ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Ico_U32: u = e->Iex.Const.con->Ico.U32; break; 979ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Ico_U16: u = 0xFFFF & (e->Iex.Const.con->Ico.U16); break; 980ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Ico_U8: u = 0xFF & (e->Iex.Const.con->Ico.U8); break; 981ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: vpanic("iselIntExpr_RI84.Iex_Const(armh)"); 982ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 983ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (fitsIn8x4(&u8, &u4, u)) { 984ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return ARMRI84_I84( (UShort)u8, (UShort)u4 ); 985ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 986ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (mayInv && fitsIn8x4(&u8, &u4, ~u)) { 987ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert(didInv); 988ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *didInv = True; 989ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return ARMRI84_I84( (UShort)u8, (UShort)u4 ); 990ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 991ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* else fail, fall through to default case */ 992ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 993ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 994ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* default case: calculate into a register and return that */ 995ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown { 996ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg r = iselIntExpr_R ( env, e ); 997ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return ARMRI84_R(r); 998ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 999ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1000ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1001ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1002ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* --------------------- RI5 --------------------- */ 1003ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1004ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Select instructions to generate 'e' into a RI5. */ 1005ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1006ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic ARMRI5* iselIntExpr_RI5 ( ISelEnv* env, IRExpr* e ) 1007ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1008ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ARMRI5* ri = iselIntExpr_RI5_wrk(env, e); 1009ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* sanity checks ... */ 1010ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (ri->tag) { 1011ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case ARMri5_I5: 1012ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return ri; 1013ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case ARMri5_R: 1014ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert(hregClass(ri->ARMri5.R.reg) == HRcInt32); 1015ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert(hregIsVirtual(ri->ARMri5.R.reg)); 1016ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return ri; 1017ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: 1018ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vpanic("iselIntExpr_RI5: unknown arm RI5 tag"); 1019ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1020ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1021ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1022ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* DO NOT CALL THIS DIRECTLY ! */ 1023ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic ARMRI5* iselIntExpr_RI5_wrk ( ISelEnv* env, IRExpr* e ) 1024ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1025ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRType ty = typeOfIRExpr(env->type_env,e); 1026ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert(ty == Ity_I32 || ty == Ity_I8); 1027ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1028ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* special case: immediate */ 1029ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->tag == Iex_Const) { 1030ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt u; /* both invalid */ 1031ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (e->Iex.Const.con->tag) { 1032ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Ico_U32: u = e->Iex.Const.con->Ico.U32; break; 1033ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Ico_U16: u = 0xFFFF & (e->Iex.Const.con->Ico.U16); break; 1034ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Ico_U8: u = 0xFF & (e->Iex.Const.con->Ico.U8); break; 1035ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: vpanic("iselIntExpr_RI5.Iex_Const(armh)"); 1036ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1037ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (u >= 1 && u <= 31) { 1038ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return ARMRI5_I5(u); 1039ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1040ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* else fail, fall through to default case */ 1041ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1042ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1043ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* default case: calculate into a register and return that */ 1044ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown { 1045ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg r = iselIntExpr_R ( env, e ); 1046ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return ARMRI5_R(r); 1047ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1048ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1049ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1050ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1051ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* ------------------- CondCode ------------------- */ 1052ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1053ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Generate code to evaluated a bit-typed expression, returning the 1054ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown condition code which would correspond when the expression would 1055ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown notionally have returned 1. */ 1056ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1057ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic ARMCondCode iselCondCode ( ISelEnv* env, IRExpr* e ) 1058ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1059ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ARMCondCode cc = iselCondCode_wrk(env,e); 1060ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert(cc != ARMcc_NV); 1061ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return cc; 1062ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1063ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1064ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic ARMCondCode iselCondCode_wrk ( ISelEnv* env, IRExpr* e ) 1065ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1066ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert(e); 1067ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert(typeOfIRExpr(env->type_env,e) == Ity_I1); 1068ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1069ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* var */ 1070ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->tag == Iex_RdTmp) { 1071ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg rTmp = lookupIRTemp(env, e->Iex.RdTmp.tmp); 1072ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* CmpOrTst doesn't modify rTmp; so this is OK. */ 1073ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ARMRI84* one = ARMRI84_I84(1,0); 1074ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_CmpOrTst(False/*test*/, rTmp, one)); 1075ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return ARMcc_NE; 1076ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1077ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1078ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Not1(e) */ 1079ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->tag == Iex_Unop && e->Iex.Unop.op == Iop_Not1) { 1080ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Generate code for the arg, and negate the test condition */ 1081ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return 1 ^ iselCondCode(env, e->Iex.Unop.arg); 1082ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1083ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1084ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* --- patterns rooted at: 32to1 --- */ 1085ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1086ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->tag == Iex_Unop 1087ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && e->Iex.Unop.op == Iop_32to1) { 1088ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg rTmp = iselIntExpr_R(env, e->Iex.Unop.arg); 1089ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ARMRI84* one = ARMRI84_I84(1,0); 1090ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_CmpOrTst(False/*test*/, rTmp, one)); 1091ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return ARMcc_NE; 1092ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1093ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1094ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* --- patterns rooted at: CmpNEZ8 --- */ 1095ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1096ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->tag == Iex_Unop 1097ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && e->Iex.Unop.op == Iop_CmpNEZ8) { 1098ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg r1 = iselIntExpr_R(env, e->Iex.Unop.arg); 1099ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ARMRI84* xFF = ARMRI84_I84(0xFF,0); 1100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_CmpOrTst(False/*!isCmp*/, r1, xFF)); 1101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return ARMcc_NE; 1102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* --- patterns rooted at: CmpNEZ32 --- */ 1105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->tag == Iex_Unop 1107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && e->Iex.Unop.op == Iop_CmpNEZ32) { 1108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg r1 = iselIntExpr_R(env, e->Iex.Unop.arg); 1109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ARMRI84* zero = ARMRI84_I84(0,0); 1110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_CmpOrTst(True/*isCmp*/, r1, zero)); 1111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return ARMcc_NE; 1112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* --- patterns rooted at: CmpNEZ64 --- */ 1115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->tag == Iex_Unop 1117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && e->Iex.Unop.op == Iop_CmpNEZ64) { 1118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg tHi, tLo; 1119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg tmp = newVRegI(env); 1120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ARMRI84* zero = ARMRI84_I84(0,0); 1121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown iselInt64Expr(&tHi, &tLo, env, e->Iex.Unop.arg); 1122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_Alu(ARMalu_OR, tmp, tHi, ARMRI84_R(tLo))); 1123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_CmpOrTst(True/*isCmp*/, tmp, zero)); 1124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return ARMcc_NE; 1125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* --- Cmp*32*(x,y) --- */ 1128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->tag == Iex_Binop 1129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && (e->Iex.Binop.op == Iop_CmpEQ32 1130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown || e->Iex.Binop.op == Iop_CmpNE32 1131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown || e->Iex.Binop.op == Iop_CmpLT32S 1132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown || e->Iex.Binop.op == Iop_CmpLT32U 1133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown || e->Iex.Binop.op == Iop_CmpLE32S 1134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown || e->Iex.Binop.op == Iop_CmpLE32U)) { 1135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselIntExpr_R(env, e->Iex.Binop.arg1); 1136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ARMRI84* argR = iselIntExpr_RI84(NULL,False, 1137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown env, e->Iex.Binop.arg2); 1138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_CmpOrTst(True/*isCmp*/, argL, argR)); 1139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (e->Iex.Binop.op) { 1140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CmpEQ32: return ARMcc_EQ; 1141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CmpNE32: return ARMcc_NE; 1142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CmpLT32S: return ARMcc_LT; 1143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CmpLT32U: return ARMcc_LO; 1144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CmpLE32S: return ARMcc_LE; 1145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CmpLE32U: return ARMcc_LS; 1146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: vpanic("iselCondCode(arm): CmpXX32"); 1147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1150436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /* const */ 1151436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /* Constant 1:Bit */ 1152436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov if (e->tag == Iex_Const) { 1153436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov HReg r; 1154436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov vassert(e->Iex.Const.con->tag == Ico_U1); 1155436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov vassert(e->Iex.Const.con->Ico.U1 == True 1156436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov || e->Iex.Const.con->Ico.U1 == False); 1157436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov r = newVRegI(env); 1158436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov addInstr(env, ARMInstr_Imm32(r, 0)); 1159436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov addInstr(env, ARMInstr_CmpOrTst(True/*isCmp*/, r, ARMRI84_R(r))); 1160436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov return e->Iex.Const.con->Ico.U1 ? ARMcc_EQ : ARMcc_NE; 1161436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } 1162436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 1163436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov // JRS 2013-Jan-03: this seems completely nonsensical 1164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* --- CasCmpEQ* --- */ 1165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Ist_Cas has a dummy argument to compare with, so comparison is 1166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown always true. */ 1167436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov //if (e->tag == Iex_Binop 1168436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov // && (e->Iex.Binop.op == Iop_CasCmpEQ32 1169436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov // || e->Iex.Binop.op == Iop_CasCmpEQ16 1170436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov // || e->Iex.Binop.op == Iop_CasCmpEQ8)) { 1171436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov // return ARMcc_AL; 1172436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov //} 1173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ppIRExpr(e); 1175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vpanic("iselCondCode"); 1176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* --------------------- Reg --------------------- */ 1180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic HReg iselIntExpr_R ( ISelEnv* env, IRExpr* e ) 1182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg r = iselIntExpr_R_wrk(env, e); 1184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* sanity checks ... */ 1185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# if 0 1186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vex_printf("\n"); ppIRExpr(e); vex_printf("\n"); 1187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 1188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert(hregClass(r) == HRcInt32); 1189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert(hregIsVirtual(r)); 1190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return r; 1191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* DO NOT CALL THIS DIRECTLY ! */ 1194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic HReg iselIntExpr_R_wrk ( ISelEnv* env, IRExpr* e ) 1195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRType ty = typeOfIRExpr(env->type_env,e); 1197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert(ty == Ity_I32 || ty == Ity_I16 || ty == Ity_I8); 1198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (e->tag) { 1200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* --------- TEMP --------- */ 1202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iex_RdTmp: { 1203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return lookupIRTemp(env, e->Iex.RdTmp.tmp); 1204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* --------- LOAD --------- */ 1207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iex_Load: { 1208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg dst = newVRegI(env); 1209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->Iex.Load.end != Iend_LE) 1211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown goto irreducible; 1212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (ty == Ity_I32) { 1214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ARMAMode1* amode = iselIntExpr_AMode1 ( env, e->Iex.Load.addr ); 1215436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov addInstr(env, ARMInstr_LdSt32(ARMcc_AL, True/*isLoad*/, dst, amode)); 1216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return dst; 1217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (ty == Ity_I16) { 1219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ARMAMode2* amode = iselIntExpr_AMode2 ( env, e->Iex.Load.addr ); 1220436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov addInstr(env, ARMInstr_LdSt16(ARMcc_AL, 1221436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov True/*isLoad*/, False/*!signedLoad*/, 1222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown dst, amode)); 1223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return dst; 1224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (ty == Ity_I8) { 1226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ARMAMode1* amode = iselIntExpr_AMode1 ( env, e->Iex.Load.addr ); 1227436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov addInstr(env, ARMInstr_LdSt8U(ARMcc_AL, True/*isLoad*/, dst, amode)); 1228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return dst; 1229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 1231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz /* --------- TERNARY OP --------- */ 1234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz case Iex_Triop: { 1235663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng//zz IRTriop *triop = e->Iex.Triop.details; 1236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz /* C3210 flags following FPU partial remainder (fprem), both 1237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz IEEE compliant (PREM1) and non-IEEE compliant (PREM). */ 1238663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng//zz if (triop->op == Iop_PRemC3210F64 1239663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng//zz || triop->op == Iop_PRem1C3210F64) { 1240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz HReg junk = newVRegF(env); 1241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz HReg dst = newVRegI(env); 1242663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng//zz HReg srcL = iselDblExpr(env, triop->arg2); 1243663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng//zz HReg srcR = iselDblExpr(env, triop->arg3); 1244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz /* XXXROUNDINGFIXME */ 1245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz /* set roundingmode here */ 1246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz addInstr(env, X86Instr_FpBinary( 1247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz e->Iex.Binop.op==Iop_PRemC3210F64 1248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz ? Xfp_PREM : Xfp_PREM1, 1249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz srcL,srcR,junk 1250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz )); 1251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz /* The previous pseudo-insn will have left the FPU's C3210 1252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz flags set correctly. So bag them. */ 1253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz addInstr(env, X86Instr_FpStSW_AX()); 1254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz addInstr(env, mk_iMOVsd_RR(hregX86_EAX(), dst)); 1255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz addInstr(env, X86Instr_Alu32R(Xalu_AND, X86RMI_Imm(0x4700), dst)); 1256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz return dst; 1257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz } 1258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz 1259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz break; 1260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz } 1261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* --------- BINARY OP --------- */ 1263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iex_Binop: { 1264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ARMAluOp aop = 0; /* invalid */ 1266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ARMShiftOp sop = 0; /* invalid */ 1267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* ADD/SUB/AND/OR/XOR */ 1269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (e->Iex.Binop.op) { 1270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_And32: { 1271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bool didInv = False; 1272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg dst = newVRegI(env); 1273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselIntExpr_R(env, e->Iex.Binop.arg1); 1274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ARMRI84* argR = iselIntExpr_RI84(&didInv, True/*mayInv*/, 1275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown env, e->Iex.Binop.arg2); 1276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_Alu(didInv ? ARMalu_BIC : ARMalu_AND, 1277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown dst, argL, argR)); 1278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return dst; 1279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Or32: aop = ARMalu_OR; goto std_binop; 1281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Xor32: aop = ARMalu_XOR; goto std_binop; 1282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Sub32: aop = ARMalu_SUB; goto std_binop; 1283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Add32: aop = ARMalu_ADD; goto std_binop; 1284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown std_binop: { 1285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg dst = newVRegI(env); 1286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselIntExpr_R(env, e->Iex.Binop.arg1); 1287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ARMRI84* argR = iselIntExpr_RI84(NULL, False/*mayInv*/, 1288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown env, e->Iex.Binop.arg2); 1289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_Alu(aop, dst, argL, argR)); 1290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return dst; 1291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: break; 1293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* SHL/SHR/SAR */ 1296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (e->Iex.Binop.op) { 1297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Shl32: sop = ARMsh_SHL; goto sh_binop; 1298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Shr32: sop = ARMsh_SHR; goto sh_binop; 1299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Sar32: sop = ARMsh_SAR; goto sh_binop; 1300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sh_binop: { 1301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg dst = newVRegI(env); 1302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselIntExpr_R(env, e->Iex.Binop.arg1); 1303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ARMRI5* argR = iselIntExpr_RI5(env, e->Iex.Binop.arg2); 1304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_Shift(sop, dst, argL, argR)); 1305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert(ty == Ity_I32); /* else the IR is ill-typed */ 1306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return dst; 1307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: break; 1309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* MUL */ 1312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->Iex.Binop.op == Iop_Mul32) { 1313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselIntExpr_R(env, e->Iex.Binop.arg1); 1314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselIntExpr_R(env, e->Iex.Binop.arg2); 1315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg dst = newVRegI(env); 1316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, mk_iMOVds_RR(hregARM_R2(), argL)); 1317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, mk_iMOVds_RR(hregARM_R3(), argR)); 1318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_Mul(ARMmul_PLAIN)); 1319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, mk_iMOVds_RR(dst, hregARM_R0())); 1320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return dst; 1321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Handle misc other ops. */ 1324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->Iex.Binop.op == Iop_Max32U) { 1326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselIntExpr_R(env, e->Iex.Binop.arg1); 1327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselIntExpr_R(env, e->Iex.Binop.arg2); 1328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg dst = newVRegI(env); 1329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_CmpOrTst(True/*isCmp*/, argL, 1330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ARMRI84_R(argR))); 1331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, mk_iMOVds_RR(dst, argL)); 1332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_CMov(ARMcc_LO, dst, ARMRI84_R(argR))); 1333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return dst; 1334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->Iex.Binop.op == Iop_CmpF64) { 1337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg dL = iselDblExpr(env, e->Iex.Binop.arg1); 1338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg dR = iselDblExpr(env, e->Iex.Binop.arg2); 1339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg dst = newVRegI(env); 1340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Do the compare (FCMPD) and set NZCV in FPSCR. Then also do 1341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown FMSTAT, so we can examine the results directly. */ 1342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_VCmpD(dL, dR)); 1343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Create in dst, the IRCmpF64Result encoded result. */ 1344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_Imm32(dst, 0)); 1345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_CMov(ARMcc_EQ, dst, ARMRI84_I84(0x40,0))); //EQ 1346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_CMov(ARMcc_MI, dst, ARMRI84_I84(0x01,0))); //LT 1347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_CMov(ARMcc_GT, dst, ARMRI84_I84(0x00,0))); //GT 1348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_CMov(ARMcc_VS, dst, ARMRI84_I84(0x45,0))); //UN 1349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return dst; 1350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->Iex.Binop.op == Iop_F64toI32S 1353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown || e->Iex.Binop.op == Iop_F64toI32U) { 1354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Wretched uglyness all round, due to having to deal 1355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown with rounding modes. Oh well. */ 1356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* FIXME: if arg1 is a constant indicating round-to-zero, 1357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown then we could skip all this arsing around with FPSCR and 1358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown simply emit FTO{S,U}IZD. */ 1359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bool syned = e->Iex.Binop.op == Iop_F64toI32S; 1360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg valD = iselDblExpr(env, e->Iex.Binop.arg2); 1361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown set_VFP_rounding_mode(env, e->Iex.Binop.arg1); 1362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* FTO{S,U}ID valF, valD */ 1363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg valF = newVRegF(env); 1364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_VCvtID(False/*!iToD*/, syned, 1365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown valF, valD)); 1366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown set_VFP_rounding_default(env); 1367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* VMOV dst, valF */ 1368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg dst = newVRegI(env); 1369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_VXferS(False/*!toS*/, valF, dst)); 1370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return dst; 1371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->Iex.Binop.op == Iop_GetElem8x8 1374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown || e->Iex.Binop.op == Iop_GetElem16x4 1375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown || e->Iex.Binop.op == Iop_GetElem32x2) { 1376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegI(env); 1377663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng HReg arg = iselNeon64Expr(env, e->Iex.Binop.arg1); 1378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt index, size; 1379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->Iex.Binop.arg2->tag != Iex_Const || 1380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown typeOfIRExpr(env->type_env, e->Iex.Binop.arg2) != Ity_I8) { 1381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vpanic("ARM target supports GetElem with constant " 1382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "second argument only\n"); 1383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown index = e->Iex.Binop.arg2->Iex.Const.con->Ico.U8; 1385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (e->Iex.Binop.op) { 1386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_GetElem8x8: vassert(index < 8); size = 0; break; 1387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_GetElem16x4: vassert(index < 4); size = 1; break; 1388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_GetElem32x2: vassert(index < 2); size = 2; break; 1389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: vassert(0); 1390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnaryS(ARMneon_GETELEMS, 1392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mkARMNRS(ARMNRS_Reg, res, 0), 1393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mkARMNRS(ARMNRS_Scalar, arg, index), 1394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown size, False)); 1395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 1396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->Iex.Binop.op == Iop_GetElem8x16 1399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown || e->Iex.Binop.op == Iop_GetElem16x8 1400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown || e->Iex.Binop.op == Iop_GetElem32x4) { 1401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegI(env); 1402663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng HReg arg = iselNeonExpr(env, e->Iex.Binop.arg1); 1403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt index, size; 1404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->Iex.Binop.arg2->tag != Iex_Const || 1405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown typeOfIRExpr(env->type_env, e->Iex.Binop.arg2) != Ity_I8) { 1406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vpanic("ARM target supports GetElem with constant " 1407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "second argument only\n"); 1408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown index = e->Iex.Binop.arg2->Iex.Const.con->Ico.U8; 1410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (e->Iex.Binop.op) { 1411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_GetElem8x16: vassert(index < 16); size = 0; break; 1412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_GetElem16x8: vassert(index < 8); size = 1; break; 1413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_GetElem32x4: vassert(index < 4); size = 2; break; 1414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: vassert(0); 1415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnaryS(ARMneon_GETELEMS, 1417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mkARMNRS(ARMNRS_Reg, res, 0), 1418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mkARMNRS(ARMNRS_Scalar, arg, index), 1419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown size, True)); 1420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 1421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* All cases involving host-side helper calls. */ 1424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown void* fn = NULL; 1425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (e->Iex.Binop.op) { 1426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Add16x2: 1427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fn = &h_generic_calc_Add16x2; break; 1428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Sub16x2: 1429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fn = &h_generic_calc_Sub16x2; break; 1430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_HAdd16Ux2: 1431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fn = &h_generic_calc_HAdd16Ux2; break; 1432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_HAdd16Sx2: 1433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fn = &h_generic_calc_HAdd16Sx2; break; 1434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_HSub16Ux2: 1435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fn = &h_generic_calc_HSub16Ux2; break; 1436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_HSub16Sx2: 1437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fn = &h_generic_calc_HSub16Sx2; break; 1438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QAdd16Sx2: 1439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fn = &h_generic_calc_QAdd16Sx2; break; 1440436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case Iop_QAdd16Ux2: 1441436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov fn = &h_generic_calc_QAdd16Ux2; break; 1442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QSub16Sx2: 1443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fn = &h_generic_calc_QSub16Sx2; break; 1444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Add8x4: 1445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fn = &h_generic_calc_Add8x4; break; 1446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Sub8x4: 1447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fn = &h_generic_calc_Sub8x4; break; 1448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_HAdd8Ux4: 1449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fn = &h_generic_calc_HAdd8Ux4; break; 1450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_HAdd8Sx4: 1451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fn = &h_generic_calc_HAdd8Sx4; break; 1452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_HSub8Ux4: 1453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fn = &h_generic_calc_HSub8Ux4; break; 1454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_HSub8Sx4: 1455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fn = &h_generic_calc_HSub8Sx4; break; 1456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QAdd8Sx4: 1457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fn = &h_generic_calc_QAdd8Sx4; break; 1458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QAdd8Ux4: 1459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fn = &h_generic_calc_QAdd8Ux4; break; 1460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QSub8Sx4: 1461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fn = &h_generic_calc_QSub8Sx4; break; 1462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QSub8Ux4: 1463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fn = &h_generic_calc_QSub8Ux4; break; 1464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Sad8Ux4: 1465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fn = &h_generic_calc_Sad8Ux4; break; 1466663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng case Iop_QAdd32S: 1467663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng fn = &h_generic_calc_QAdd32S; break; 1468663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng case Iop_QSub32S: 1469663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng fn = &h_generic_calc_QSub32S; break; 1470663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng case Iop_QSub16Ux2: 1471663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng fn = &h_generic_calc_QSub16Ux2; break; 1472436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case Iop_DivU32: 1473436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov fn = &h_calc_udiv32_w_arm_semantics; break; 1474436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case Iop_DivS32: 1475436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov fn = &h_calc_sdiv32_w_arm_semantics; break; 1476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: 1477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 1478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (fn) { 1481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg regL = iselIntExpr_R(env, e->Iex.Binop.arg1); 1482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg regR = iselIntExpr_R(env, e->Iex.Binop.arg2); 1483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegI(env); 1484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, mk_iMOVds_RR(hregARM_R0(), regL)); 1485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, mk_iMOVds_RR(hregARM_R1(), regR)); 1486436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov addInstr(env, ARMInstr_Call( ARMcc_AL, (HWord)Ptr_to_ULong(fn), 1487436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 2, mk_RetLoc_simple(RLPri_Int) )); 1488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, mk_iMOVds_RR(res, hregARM_R0())); 1489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 1490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 1493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* --------- UNARY OP --------- */ 1496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iex_Unop: { 1497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz /* 1Uto8(32to1(expr32)) */ 1499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz if (e->Iex.Unop.op == Iop_1Uto8) { 1500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz DECLARE_PATTERN(p_32to1_then_1Uto8); 1501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz DEFINE_PATTERN(p_32to1_then_1Uto8, 1502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz unop(Iop_1Uto8,unop(Iop_32to1,bind(0)))); 1503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz if (matchIRExpr(&mi,p_32to1_then_1Uto8,e)) { 1504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz IRExpr* expr32 = mi.bindee[0]; 1505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz HReg dst = newVRegI(env); 1506ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz HReg src = iselIntExpr_R(env, expr32); 1507ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz addInstr(env, mk_iMOVsd_RR(src,dst) ); 1508ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz addInstr(env, X86Instr_Alu32R(Xalu_AND, 1509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz X86RMI_Imm(1), dst)); 1510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz return dst; 1511ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz } 1512ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz } 1513ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz 1514ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz /* 8Uto32(LDle(expr32)) */ 1515ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz if (e->Iex.Unop.op == Iop_8Uto32) { 1516ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz DECLARE_PATTERN(p_LDle8_then_8Uto32); 1517ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz DEFINE_PATTERN(p_LDle8_then_8Uto32, 1518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz unop(Iop_8Uto32, 1519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz IRExpr_Load(Iend_LE,Ity_I8,bind(0))) ); 1520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz if (matchIRExpr(&mi,p_LDle8_then_8Uto32,e)) { 1521ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz HReg dst = newVRegI(env); 1522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz X86AMode* amode = iselIntExpr_AMode ( env, mi.bindee[0] ); 1523ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz addInstr(env, X86Instr_LoadEX(1,False,amode,dst)); 1524ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz return dst; 1525ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz } 1526ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz } 1527ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz 1528ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz /* 8Sto32(LDle(expr32)) */ 1529ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz if (e->Iex.Unop.op == Iop_8Sto32) { 1530ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz DECLARE_PATTERN(p_LDle8_then_8Sto32); 1531ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz DEFINE_PATTERN(p_LDle8_then_8Sto32, 1532ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz unop(Iop_8Sto32, 1533ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz IRExpr_Load(Iend_LE,Ity_I8,bind(0))) ); 1534ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz if (matchIRExpr(&mi,p_LDle8_then_8Sto32,e)) { 1535ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz HReg dst = newVRegI(env); 1536ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz X86AMode* amode = iselIntExpr_AMode ( env, mi.bindee[0] ); 1537ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz addInstr(env, X86Instr_LoadEX(1,True,amode,dst)); 1538ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz return dst; 1539ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz } 1540ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz } 1541ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz 1542ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz /* 16Uto32(LDle(expr32)) */ 1543ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz if (e->Iex.Unop.op == Iop_16Uto32) { 1544ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz DECLARE_PATTERN(p_LDle16_then_16Uto32); 1545ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz DEFINE_PATTERN(p_LDle16_then_16Uto32, 1546ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz unop(Iop_16Uto32, 1547ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz IRExpr_Load(Iend_LE,Ity_I16,bind(0))) ); 1548ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz if (matchIRExpr(&mi,p_LDle16_then_16Uto32,e)) { 1549ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz HReg dst = newVRegI(env); 1550ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz X86AMode* amode = iselIntExpr_AMode ( env, mi.bindee[0] ); 1551ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz addInstr(env, X86Instr_LoadEX(2,False,amode,dst)); 1552ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz return dst; 1553ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz } 1554ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz } 1555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz 1556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz /* 8Uto32(GET:I8) */ 1557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz if (e->Iex.Unop.op == Iop_8Uto32) { 1558ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz if (e->Iex.Unop.arg->tag == Iex_Get) { 1559ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz HReg dst; 1560ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz X86AMode* amode; 1561ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz vassert(e->Iex.Unop.arg->Iex.Get.ty == Ity_I8); 1562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz dst = newVRegI(env); 1563ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz amode = X86AMode_IR(e->Iex.Unop.arg->Iex.Get.offset, 1564ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz hregX86_EBP()); 1565ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz addInstr(env, X86Instr_LoadEX(1,False,amode,dst)); 1566ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz return dst; 1567ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz } 1568ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz } 1569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz 1570ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz /* 16to32(GET:I16) */ 1571ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz if (e->Iex.Unop.op == Iop_16Uto32) { 1572ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz if (e->Iex.Unop.arg->tag == Iex_Get) { 1573ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz HReg dst; 1574ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz X86AMode* amode; 1575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz vassert(e->Iex.Unop.arg->Iex.Get.ty == Ity_I16); 1576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz dst = newVRegI(env); 1577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz amode = X86AMode_IR(e->Iex.Unop.arg->Iex.Get.offset, 1578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz hregX86_EBP()); 1579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz addInstr(env, X86Instr_LoadEX(2,False,amode,dst)); 1580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz return dst; 1581ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz } 1582ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz } 1583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1584ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (e->Iex.Unop.op) { 1585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_8Uto32: { 1586ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg dst = newVRegI(env); 1587ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg src = iselIntExpr_R(env, e->Iex.Unop.arg); 1588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_Alu(ARMalu_AND, 1589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown dst, src, ARMRI84_I84(0xFF,0))); 1590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return dst; 1591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz case Iop_8Uto16: 1593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz case Iop_8Uto32: 1594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz case Iop_16Uto32: { 1595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz HReg dst = newVRegI(env); 1596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz HReg src = iselIntExpr_R(env, e->Iex.Unop.arg); 1597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz UInt mask = e->Iex.Unop.op==Iop_16Uto32 ? 0xFFFF : 0xFF; 1598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz addInstr(env, mk_iMOVsd_RR(src,dst) ); 1599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz addInstr(env, X86Instr_Alu32R(Xalu_AND, 1600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz X86RMI_Imm(mask), dst)); 1601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz return dst; 1602ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz } 1603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz case Iop_8Sto16: 1604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz case Iop_8Sto32: 1605ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_16Uto32: { 1606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg dst = newVRegI(env); 1607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg src = iselIntExpr_R(env, e->Iex.Unop.arg); 1608ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ARMRI5* amt = ARMRI5_I5(16); 1609ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_Shift(ARMsh_SHL, dst, src, amt)); 1610ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_Shift(ARMsh_SHR, dst, dst, amt)); 1611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return dst; 1612ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1613ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_8Sto32: 1614ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_16Sto32: { 1615ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg dst = newVRegI(env); 1616ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg src = iselIntExpr_R(env, e->Iex.Unop.arg); 1617ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ARMRI5* amt = ARMRI5_I5(e->Iex.Unop.op==Iop_16Sto32 ? 16 : 24); 1618ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_Shift(ARMsh_SHL, dst, src, amt)); 1619ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_Shift(ARMsh_SAR, dst, dst, amt)); 1620ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return dst; 1621ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1622ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz case Iop_Not8: 1623ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz case Iop_Not16: 1624ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Not32: { 1625ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg dst = newVRegI(env); 1626ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg src = iselIntExpr_R(env, e->Iex.Unop.arg); 1627ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_Unary(ARMun_NOT, dst, src)); 1628ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return dst; 1629ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1630ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_64HIto32: { 1631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg rHi, rLo; 1632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown iselInt64Expr(&rHi,&rLo, env, e->Iex.Unop.arg); 1633ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return rHi; /* and abandon rLo .. poor wee thing :-) */ 1634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_64to32: { 1636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg rHi, rLo; 1637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown iselInt64Expr(&rHi,&rLo, env, e->Iex.Unop.arg); 1638ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return rLo; /* similar stupid comment to the above ... */ 1639ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1640ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_64to8: { 1641ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg rHi, rLo; 1642663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng if (env->hwcaps & VEX_HWCAPS_ARM_NEON) { 1643ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg tHi = newVRegI(env); 1644ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg tLo = newVRegI(env); 1645ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg tmp = iselNeon64Expr(env, e->Iex.Unop.arg); 1646ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_VXferD(False, tmp, tHi, tLo)); 1647ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown rHi = tHi; 1648ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown rLo = tLo; 1649ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 1650ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown iselInt64Expr(&rHi,&rLo, env, e->Iex.Unop.arg); 1651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1652ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return rLo; 1653ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1654436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 1655ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_1Uto32: 1656436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /* 1Uto32(tmp). Since I1 values generated into registers 1657436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov are guaranteed to have value either only zero or one, 1658436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov we can simply return the value of the register in this 1659436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case. */ 1660436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov if (e->Iex.Unop.arg->tag == Iex_RdTmp) { 1661436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov HReg dst = lookupIRTemp(env, e->Iex.Unop.arg->Iex.RdTmp.tmp); 1662436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov return dst; 1663436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } 1664436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /* else fall through */ 1665ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_1Uto8: { 1666ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg dst = newVRegI(env); 1667ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ARMCondCode cond = iselCondCode(env, e->Iex.Unop.arg); 1668ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_Mov(dst, ARMRI84_I84(0,0))); 1669ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_CMov(cond, dst, ARMRI84_I84(1,0))); 1670ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return dst; 1671ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1672ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1673ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_1Sto32: { 1674ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg dst = newVRegI(env); 1675ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ARMCondCode cond = iselCondCode(env, e->Iex.Unop.arg); 1676ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ARMRI5* amt = ARMRI5_I5(31); 1677ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* This is really rough. We could do much better here; 1678ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown perhaps mvn{cond} dst, #0 as the second insn? 1679ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (same applies to 1Sto64) */ 1680ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_Mov(dst, ARMRI84_I84(0,0))); 1681ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_CMov(cond, dst, ARMRI84_I84(1,0))); 1682ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_Shift(ARMsh_SHL, dst, dst, amt)); 1683ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_Shift(ARMsh_SAR, dst, dst, amt)); 1684ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return dst; 1685ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1686ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1687ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1688ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz case Iop_1Sto8: 1689ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz case Iop_1Sto16: 1690ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz case Iop_1Sto32: { 1691ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz /* could do better than this, but for now ... */ 1692ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz HReg dst = newVRegI(env); 1693ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz X86CondCode cond = iselCondCode(env, e->Iex.Unop.arg); 1694ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz addInstr(env, X86Instr_Set32(cond,dst)); 1695ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz addInstr(env, X86Instr_Sh32(Xsh_SHL, 31, dst)); 1696ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz addInstr(env, X86Instr_Sh32(Xsh_SAR, 31, dst)); 1697ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz return dst; 1698ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz } 1699ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz case Iop_Ctz32: { 1700ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz /* Count trailing zeroes, implemented by x86 'bsfl' */ 1701ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz HReg dst = newVRegI(env); 1702ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz HReg src = iselIntExpr_R(env, e->Iex.Unop.arg); 1703ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz addInstr(env, X86Instr_Bsfr32(True,src,dst)); 1704ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz return dst; 1705ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz } 1706ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Clz32: { 1707ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Count leading zeroes; easy on ARM. */ 1708ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg dst = newVRegI(env); 1709ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg src = iselIntExpr_R(env, e->Iex.Unop.arg); 1710ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_Unary(ARMun_CLZ, dst, src)); 1711ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return dst; 1712ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1713ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1714ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CmpwNEZ32: { 1715ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg dst = newVRegI(env); 1716ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg src = iselIntExpr_R(env, e->Iex.Unop.arg); 1717ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_Unary(ARMun_NEG, dst, src)); 1718ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_Alu(ARMalu_OR, dst, dst, ARMRI84_R(src))); 1719ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_Shift(ARMsh_SAR, dst, dst, ARMRI5_I5(31))); 1720ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return dst; 1721ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1722ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1723ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Left32: { 1724ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg dst = newVRegI(env); 1725ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg src = iselIntExpr_R(env, e->Iex.Unop.arg); 1726ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_Unary(ARMun_NEG, dst, src)); 1727ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_Alu(ARMalu_OR, dst, dst, ARMRI84_R(src))); 1728ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return dst; 1729ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1730ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1731ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz case Iop_V128to32: { 1732ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz HReg dst = newVRegI(env); 1733ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz HReg vec = iselVecExpr(env, e->Iex.Unop.arg); 1734ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz X86AMode* esp0 = X86AMode_IR(0, hregX86_ESP()); 1735ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz sub_from_esp(env, 16); 1736ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz addInstr(env, X86Instr_SseLdSt(False/*store*/, vec, esp0)); 1737ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz addInstr(env, X86Instr_Alu32R( Xalu_MOV, X86RMI_Mem(esp0), dst )); 1738ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz add_to_esp(env, 16); 1739ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz return dst; 1740ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz } 1741ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz 1742ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_ReinterpF32asI32: { 1743ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg dst = newVRegI(env); 1744ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg src = iselFltExpr(env, e->Iex.Unop.arg); 1745ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_VXferS(False/*!toS*/, src, dst)); 1746ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return dst; 1747ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1748ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1749ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz 1750ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz case Iop_16to8: 1751ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_32to8: 1752ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_32to16: 1753ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* These are no-ops. */ 1754ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return iselIntExpr_R(env, e->Iex.Unop.arg); 1755ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1756ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: 1757ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 1758ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1759ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1760ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* All Unop cases involving host-side helper calls. */ 1761ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown void* fn = NULL; 1762ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (e->Iex.Unop.op) { 1763ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CmpNEZ16x2: 1764ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fn = &h_generic_calc_CmpNEZ16x2; break; 1765ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CmpNEZ8x4: 1766ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fn = &h_generic_calc_CmpNEZ8x4; break; 1767ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: 1768ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 1769ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1770ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1771ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (fn) { 1772ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg arg = iselIntExpr_R(env, e->Iex.Unop.arg); 1773ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegI(env); 1774ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, mk_iMOVds_RR(hregARM_R0(), arg)); 1775436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov addInstr(env, ARMInstr_Call( ARMcc_AL, (HWord)Ptr_to_ULong(fn), 1776436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 1, mk_RetLoc_simple(RLPri_Int) )); 1777ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, mk_iMOVds_RR(res, hregARM_R0())); 1778ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 1779ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1780ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1781ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 1782ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1783ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1784ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* --------- GET --------- */ 1785ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iex_Get: { 1786ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (ty == Ity_I32 1787ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && 0 == (e->Iex.Get.offset & 3) 1788ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && e->Iex.Get.offset < 4096-4) { 1789ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg dst = newVRegI(env); 1790ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_LdSt32( 1791436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov ARMcc_AL, True/*isLoad*/, 1792ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown dst, 1793ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ARMAMode1_RI(hregARM_R8(), e->Iex.Get.offset))); 1794ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return dst; 1795ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1796ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz if (ty == Ity_I8 || ty == Ity_I16) { 1797ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz HReg dst = newVRegI(env); 1798ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz addInstr(env, X86Instr_LoadEX( 1799ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz toUChar(ty==Ity_I8 ? 1 : 2), 1800ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz False, 1801ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz X86AMode_IR(e->Iex.Get.offset,hregX86_EBP()), 1802ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz dst)); 1803ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz return dst; 1804ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz } 1805ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 1806ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1807ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1808ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz case Iex_GetI: { 1809ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz X86AMode* am 1810ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz = genGuestArrayOffset( 1811ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz env, e->Iex.GetI.descr, 1812ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz e->Iex.GetI.ix, e->Iex.GetI.bias ); 1813ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz HReg dst = newVRegI(env); 1814ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz if (ty == Ity_I8) { 1815ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz addInstr(env, X86Instr_LoadEX( 1, False, am, dst )); 1816ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz return dst; 1817ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz } 1818ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz if (ty == Ity_I32) { 1819ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz addInstr(env, X86Instr_Alu32R(Xalu_MOV, X86RMI_Mem(am), dst)); 1820ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz return dst; 1821ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz } 1822ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz break; 1823ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz } 1824ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1825ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* --------- CCALL --------- */ 1826ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iex_CCall: { 1827ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg dst = newVRegI(env); 1828ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert(ty == e->Iex.CCall.retty); 1829ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1830436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /* be very restrictive for now. Only 32/64-bit ints allowed for 1831436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov args, and 32 bits for return type. Don't forget to change 1832436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov the RetLoc if more types are allowed in future. */ 1833ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->Iex.CCall.retty != Ity_I32) 1834ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown goto irreducible; 1835ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1836ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Marshal args, do the call, clear stack. */ 1837436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov UInt addToSp = 0; 1838436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov RetLoc rloc = mk_RetLoc_INVALID(); 1839436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov Bool ok = doHelperCall( &addToSp, &rloc, env, NULL/*guard*/, 1840436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov e->Iex.CCall.cee, e->Iex.CCall.retty, 1841436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov e->Iex.CCall.args ); 1842436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /* */ 1843ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (ok) { 1844436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov vassert(is_sane_RetLoc(rloc)); 1845436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov vassert(rloc.pri == RLPri_Int); 1846436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov vassert(addToSp == 0); 1847ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, mk_iMOVds_RR(dst, hregARM_R0())); 1848ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return dst; 1849ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1850ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* else fall through; will hit the irreducible: label */ 1851ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1852ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1853ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* --------- LITERAL --------- */ 1854ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* 32 literals */ 1855ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iex_Const: { 1856ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt u = 0; 1857ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg dst = newVRegI(env); 1858ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (e->Iex.Const.con->tag) { 1859ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Ico_U32: u = e->Iex.Const.con->Ico.U32; break; 1860ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Ico_U16: u = 0xFFFF & (e->Iex.Const.con->Ico.U16); break; 1861ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Ico_U8: u = 0xFF & (e->Iex.Const.con->Ico.U8); break; 1862ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: ppIRExpr(e); vpanic("iselIntExpr_R.Iex_Const(arm)"); 1863ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1864ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_Imm32(dst, u)); 1865ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return dst; 1866ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1867ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1868ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* --------- MULTIPLEX --------- */ 1869436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case Iex_ITE: { // VFD 1870436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /* ITE(ccexpr, iftrue, iffalse) */ 1871436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov if (ty == Ity_I32) { 1872ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ARMCondCode cc; 1873436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov HReg r1 = iselIntExpr_R(env, e->Iex.ITE.iftrue); 1874436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov ARMRI84* r0 = iselIntExpr_RI84(NULL, False, env, e->Iex.ITE.iffalse); 1875ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg dst = newVRegI(env); 1876436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov addInstr(env, mk_iMOVds_RR(dst, r1)); 1877436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov cc = iselCondCode(env, e->Iex.ITE.cond); 1878ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_CMov(cc ^ 1, dst, r0)); 1879ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return dst; 1880ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1881ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 1882ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1883ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1884ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: 1885ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 1886ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } /* switch (e->tag) */ 1887ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1888ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* We get here if no pattern matched. */ 1889ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown irreducible: 1890ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ppIRExpr(e); 1891ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vpanic("iselIntExpr_R: cannot reduce tree"); 1892ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1893ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1894ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1895ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* -------------------- 64-bit -------------------- */ 1896ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1897ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Compute a 64-bit value into a register pair, which is returned as 1898ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown the first two parameters. As with iselIntExpr_R, these may be 1899ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown either real or virtual regs; in any case they must not be changed 1900ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown by subsequent code emitted by the caller. */ 1901ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1902ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void iselInt64Expr ( HReg* rHi, HReg* rLo, ISelEnv* env, IRExpr* e ) 1903ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1904ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown iselInt64Expr_wrk(rHi, rLo, env, e); 1905ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# if 0 1906ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vex_printf("\n"); ppIRExpr(e); vex_printf("\n"); 1907ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 1908ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert(hregClass(*rHi) == HRcInt32); 1909ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert(hregIsVirtual(*rHi)); 1910ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert(hregClass(*rLo) == HRcInt32); 1911ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert(hregIsVirtual(*rLo)); 1912ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1913ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1914ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* DO NOT CALL THIS DIRECTLY ! */ 1915ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void iselInt64Expr_wrk ( HReg* rHi, HReg* rLo, ISelEnv* env, IRExpr* e ) 1916ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1917ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert(e); 1918ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert(typeOfIRExpr(env->type_env,e) == Ity_I64); 1919ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1920ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* 64-bit literal */ 1921ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->tag == Iex_Const) { 1922ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ULong w64 = e->Iex.Const.con->Ico.U64; 1923ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt wHi = toUInt(w64 >> 32); 1924ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt wLo = toUInt(w64); 1925ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg tHi = newVRegI(env); 1926ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg tLo = newVRegI(env); 1927ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert(e->Iex.Const.con->tag == Ico_U64); 1928ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_Imm32(tHi, wHi)); 1929ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_Imm32(tLo, wLo)); 1930ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *rHi = tHi; 1931ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *rLo = tLo; 1932ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return; 1933ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1934ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1935ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* read 64-bit IRTemp */ 1936ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->tag == Iex_RdTmp) { 1937663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng if (env->hwcaps & VEX_HWCAPS_ARM_NEON) { 1938ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg tHi = newVRegI(env); 1939ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg tLo = newVRegI(env); 1940ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg tmp = iselNeon64Expr(env, e); 1941ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_VXferD(False, tmp, tHi, tLo)); 1942ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *rHi = tHi; 1943ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *rLo = tLo; 1944ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 1945ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown lookupIRTemp64( rHi, rLo, env, e->Iex.RdTmp.tmp); 1946ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1947ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return; 1948ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1949ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1950ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* 64-bit load */ 1951ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->tag == Iex_Load && e->Iex.Load.end == Iend_LE) { 1952ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg tLo, tHi, rA; 1953ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert(e->Iex.Load.ty == Ity_I64); 1954ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown rA = iselIntExpr_R(env, e->Iex.Load.addr); 1955ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tHi = newVRegI(env); 1956ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tLo = newVRegI(env); 1957436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov addInstr(env, ARMInstr_LdSt32(ARMcc_AL, True/*isLoad*/, 1958436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov tHi, ARMAMode1_RI(rA, 4))); 1959436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov addInstr(env, ARMInstr_LdSt32(ARMcc_AL, True/*isLoad*/, 1960436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov tLo, ARMAMode1_RI(rA, 0))); 1961ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *rHi = tHi; 1962ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *rLo = tLo; 1963ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return; 1964ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1965ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1966ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* 64-bit GET */ 1967ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->tag == Iex_Get) { 1968ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ARMAMode1* am0 = ARMAMode1_RI(hregARM_R8(), e->Iex.Get.offset + 0); 1969ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ARMAMode1* am4 = ARMAMode1_RI(hregARM_R8(), e->Iex.Get.offset + 4); 1970ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg tHi = newVRegI(env); 1971ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg tLo = newVRegI(env); 1972436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov addInstr(env, ARMInstr_LdSt32(ARMcc_AL, True/*isLoad*/, tHi, am4)); 1973436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov addInstr(env, ARMInstr_LdSt32(ARMcc_AL, True/*isLoad*/, tLo, am0)); 1974ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *rHi = tHi; 1975ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *rLo = tLo; 1976ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return; 1977ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1978ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1979ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* --------- BINARY ops --------- */ 1980ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->tag == Iex_Binop) { 1981ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (e->Iex.Binop.op) { 1982ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1983ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* 32 x 32 -> 64 multiply */ 1984ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_MullS32: 1985ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_MullU32: { 1986ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselIntExpr_R(env, e->Iex.Binop.arg1); 1987ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselIntExpr_R(env, e->Iex.Binop.arg2); 1988ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg tHi = newVRegI(env); 1989ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg tLo = newVRegI(env); 1990436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov ARMMulOp mop = e->Iex.Binop.op == Iop_MullS32 1991ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ? ARMmul_SX : ARMmul_ZX; 1992ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, mk_iMOVds_RR(hregARM_R2(), argL)); 1993ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, mk_iMOVds_RR(hregARM_R3(), argR)); 1994ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_Mul(mop)); 1995ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, mk_iMOVds_RR(tHi, hregARM_R1())); 1996ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, mk_iMOVds_RR(tLo, hregARM_R0())); 1997ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *rHi = tHi; 1998ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *rLo = tLo; 1999ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return; 2000ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2001ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2002ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Or64: { 2003ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg xLo, xHi, yLo, yHi; 2004ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg tHi = newVRegI(env); 2005ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg tLo = newVRegI(env); 2006ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown iselInt64Expr(&xHi, &xLo, env, e->Iex.Binop.arg1); 2007ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown iselInt64Expr(&yHi, &yLo, env, e->Iex.Binop.arg2); 2008ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_Alu(ARMalu_OR, tHi, xHi, ARMRI84_R(yHi))); 2009ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_Alu(ARMalu_OR, tLo, xLo, ARMRI84_R(yLo))); 2010ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *rHi = tHi; 2011ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *rLo = tLo; 2012ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return; 2013ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2014ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2015ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Add64: { 2016ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg xLo, xHi, yLo, yHi; 2017ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg tHi = newVRegI(env); 2018ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg tLo = newVRegI(env); 2019ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown iselInt64Expr(&xHi, &xLo, env, e->Iex.Binop.arg1); 2020ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown iselInt64Expr(&yHi, &yLo, env, e->Iex.Binop.arg2); 2021ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_Alu(ARMalu_ADDS, tLo, xLo, ARMRI84_R(yLo))); 2022ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_Alu(ARMalu_ADC, tHi, xHi, ARMRI84_R(yHi))); 2023ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *rHi = tHi; 2024ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *rLo = tLo; 2025ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return; 2026ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2027ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2028ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* 32HLto64(e1,e2) */ 2029ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_32HLto64: { 2030ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *rHi = iselIntExpr_R(env, e->Iex.Binop.arg1); 2031ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *rLo = iselIntExpr_R(env, e->Iex.Binop.arg2); 2032ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return; 2033ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2034ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2035ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: 2036ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 2037ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2038ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2039ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2040ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* --------- UNARY ops --------- */ 2041ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->tag == Iex_Unop) { 2042ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (e->Iex.Unop.op) { 2043ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2044ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* ReinterpF64asI64 */ 2045ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_ReinterpF64asI64: { 2046ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg dstHi = newVRegI(env); 2047ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg dstLo = newVRegI(env); 2048ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg src = iselDblExpr(env, e->Iex.Unop.arg); 2049ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_VXferD(False/*!toD*/, src, dstHi, dstLo)); 2050ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *rHi = dstHi; 2051ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *rLo = dstLo; 2052ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return; 2053ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2054ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2055ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Left64(e) */ 2056ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Left64: { 2057ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg yLo, yHi; 2058ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg tHi = newVRegI(env); 2059ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg tLo = newVRegI(env); 2060ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg zero = newVRegI(env); 2061ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* yHi:yLo = arg */ 2062ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown iselInt64Expr(&yHi, &yLo, env, e->Iex.Unop.arg); 2063ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* zero = 0 */ 2064ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_Imm32(zero, 0)); 2065ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* tLo = 0 - yLo, and set carry */ 2066ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_Alu(ARMalu_SUBS, 2067ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tLo, zero, ARMRI84_R(yLo))); 2068ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* tHi = 0 - yHi - carry */ 2069ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_Alu(ARMalu_SBC, 2070ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tHi, zero, ARMRI84_R(yHi))); 2071ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* So now we have tHi:tLo = -arg. To finish off, or 'arg' 2072ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown back in, so as to give the final result 2073ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tHi:tLo = arg | -arg. */ 2074ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_Alu(ARMalu_OR, tHi, tHi, ARMRI84_R(yHi))); 2075ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_Alu(ARMalu_OR, tLo, tLo, ARMRI84_R(yLo))); 2076ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *rHi = tHi; 2077ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *rLo = tLo; 2078ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return; 2079ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2080ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2081ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* CmpwNEZ64(e) */ 2082ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CmpwNEZ64: { 2083ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg srcLo, srcHi; 2084ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg tmp1 = newVRegI(env); 2085ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg tmp2 = newVRegI(env); 2086ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* srcHi:srcLo = arg */ 2087ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown iselInt64Expr(&srcHi, &srcLo, env, e->Iex.Unop.arg); 2088ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* tmp1 = srcHi | srcLo */ 2089ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_Alu(ARMalu_OR, 2090ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tmp1, srcHi, ARMRI84_R(srcLo))); 2091ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* tmp2 = (tmp1 | -tmp1) >>s 31 */ 2092ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_Unary(ARMun_NEG, tmp2, tmp1)); 2093ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_Alu(ARMalu_OR, 2094ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tmp2, tmp2, ARMRI84_R(tmp1))); 2095ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_Shift(ARMsh_SAR, 2096ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tmp2, tmp2, ARMRI5_I5(31))); 2097ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *rHi = tmp2; 2098ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *rLo = tmp2; 2099ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return; 2100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_1Sto64: { 2103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg dst = newVRegI(env); 2104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ARMCondCode cond = iselCondCode(env, e->Iex.Unop.arg); 2105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ARMRI5* amt = ARMRI5_I5(31); 2106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* This is really rough. We could do much better here; 2107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown perhaps mvn{cond} dst, #0 as the second insn? 2108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (same applies to 1Sto32) */ 2109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_Mov(dst, ARMRI84_I84(0,0))); 2110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_CMov(cond, dst, ARMRI84_I84(1,0))); 2111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_Shift(ARMsh_SHL, dst, dst, amt)); 2112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_Shift(ARMsh_SAR, dst, dst, amt)); 2113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *rHi = dst; 2114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *rLo = dst; 2115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return; 2116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: 2119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 2120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } /* if (e->tag == Iex_Unop) */ 2122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* --------- MULTIPLEX --------- */ 2124436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov if (e->tag == Iex_ITE) { // VFD 2125436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov IRType tyC; 2126436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov HReg r1hi, r1lo, r0hi, r0lo, dstHi, dstLo; 2127436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov ARMCondCode cc; 2128436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov tyC = typeOfIRExpr(env->type_env,e->Iex.ITE.cond); 2129436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov vassert(tyC == Ity_I1); 2130436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov iselInt64Expr(&r1hi, &r1lo, env, e->Iex.ITE.iftrue); 2131436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov iselInt64Expr(&r0hi, &r0lo, env, e->Iex.ITE.iffalse); 2132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown dstHi = newVRegI(env); 2133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown dstLo = newVRegI(env); 2134436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov addInstr(env, mk_iMOVds_RR(dstHi, r1hi)); 2135436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov addInstr(env, mk_iMOVds_RR(dstLo, r1lo)); 2136436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov cc = iselCondCode(env, e->Iex.ITE.cond); 2137436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov addInstr(env, ARMInstr_CMov(cc ^ 1, dstHi, ARMRI84_R(r0hi))); 2138436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov addInstr(env, ARMInstr_CMov(cc ^ 1, dstLo, ARMRI84_R(r0lo))); 2139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *rHi = dstHi; 2140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *rLo = dstLo; 2141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return; 2142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* It is convenient sometimes to call iselInt64Expr even when we 2145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown have NEON support (e.g. in do_helper_call we need 64-bit 2146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown arguments as 2 x 32 regs). */ 2147663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng if (env->hwcaps & VEX_HWCAPS_ARM_NEON) { 2148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg tHi = newVRegI(env); 2149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg tLo = newVRegI(env); 2150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg tmp = iselNeon64Expr(env, e); 2151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_VXferD(False, tmp, tHi, tLo)); 2152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *rHi = tHi; 2153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *rLo = tLo; 2154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return ; 2155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ppIRExpr(e); 2158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vpanic("iselInt64Expr"); 2159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 2160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------*/ 2163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- ISEL: Vector (NEON) expressions (64 or 128 bit) ---*/ 2164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------*/ 2165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic HReg iselNeon64Expr ( ISelEnv* env, IRExpr* e ) 2167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 2168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg r = iselNeon64Expr_wrk( env, e ); 2169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert(hregClass(r) == HRcFlt64); 2170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert(hregIsVirtual(r)); 2171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return r; 2172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 2173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* DO NOT CALL THIS DIRECTLY */ 2175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic HReg iselNeon64Expr_wrk ( ISelEnv* env, IRExpr* e ) 2176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 2177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRType ty = typeOfIRExpr(env->type_env, e); 2178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown MatchInfo mi; 2179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert(e); 2180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert(ty == Ity_I64); 2181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->tag == Iex_RdTmp) { 2183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return lookupIRTemp(env, e->Iex.RdTmp.tmp); 2184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->tag == Iex_Const) { 2187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg rLo, rHi; 2188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegD(env); 2189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown iselInt64Expr(&rHi, &rLo, env, e); 2190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_VXferD(True/*toD*/, res, rHi, rLo)); 2191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 2192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* 64-bit load */ 2195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->tag == Iex_Load && e->Iex.Load.end == Iend_LE) { 2196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegD(env); 2197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ARMAModeN* am = iselIntExpr_AModeN(env, e->Iex.Load.addr); 2198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert(ty == Ity_I64); 2199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NLdStD(True, res, am)); 2200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 2201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* 64-bit GET */ 2204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->tag == Iex_Get) { 2205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg addr = newVRegI(env); 2206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegD(env); 2207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert(ty == Ity_I64); 2208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_Add32(addr, hregARM_R8(), e->Iex.Get.offset)); 2209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NLdStD(True, res, mkARMAModeN_R(addr))); 2210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 2211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* --------- BINARY ops --------- */ 2214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->tag == Iex_Binop) { 2215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (e->Iex.Binop.op) { 2216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* 32 x 32 -> 64 multiply */ 2218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_MullS32: 2219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_MullU32: { 2220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg rLo, rHi; 2221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegD(env); 2222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown iselInt64Expr(&rHi, &rLo, env, e); 2223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_VXferD(True/*toD*/, res, rHi, rLo)); 2224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 2225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_And64: { 2228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegD(env); 2229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeon64Expr(env, e->Iex.Binop.arg1); 2230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeon64Expr(env, e->Iex.Binop.arg2); 2231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NBinary(ARMneon_VAND, 2232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, argR, 4, False)); 2233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 2234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Or64: { 2236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegD(env); 2237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeon64Expr(env, e->Iex.Binop.arg1); 2238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeon64Expr(env, e->Iex.Binop.arg2); 2239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NBinary(ARMneon_VORR, 2240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, argR, 4, False)); 2241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 2242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Xor64: { 2244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegD(env); 2245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeon64Expr(env, e->Iex.Binop.arg1); 2246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeon64Expr(env, e->Iex.Binop.arg2); 2247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NBinary(ARMneon_VXOR, 2248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, argR, 4, False)); 2249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 2250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* 32HLto64(e1,e2) */ 2253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_32HLto64: { 2254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg rHi = iselIntExpr_R(env, e->Iex.Binop.arg1); 2255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg rLo = iselIntExpr_R(env, e->Iex.Binop.arg2); 2256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegD(env); 2257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_VXferD(True/*toD*/, res, rHi, rLo)); 2258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 2259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Add8x8: 2262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Add16x4: 2263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Add32x2: 2264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Add64: { 2265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegD(env); 2266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeon64Expr(env, e->Iex.Binop.arg1); 2267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeon64Expr(env, e->Iex.Binop.arg2); 2268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size; 2269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (e->Iex.Binop.op) { 2270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Add8x8: size = 0; break; 2271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Add16x4: size = 1; break; 2272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Add32x2: size = 2; break; 2273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Add64: size = 3; break; 2274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: vassert(0); 2275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NBinary(ARMneon_VADD, 2277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, argR, size, False)); 2278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 2279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Add32Fx2: { 2281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegD(env); 2282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeon64Expr(env, e->Iex.Binop.arg1); 2283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeon64Expr(env, e->Iex.Binop.arg2); 2284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size = 0; 2285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NBinary(ARMneon_VADDFP, 2286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, argR, size, False)); 2287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 2288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Recps32Fx2: { 2290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegD(env); 2291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeon64Expr(env, e->Iex.Binop.arg1); 2292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeon64Expr(env, e->Iex.Binop.arg2); 2293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size = 0; 2294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NBinary(ARMneon_VRECPS, 2295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, argR, size, False)); 2296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 2297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Rsqrts32Fx2: { 2299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegD(env); 2300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeon64Expr(env, e->Iex.Binop.arg1); 2301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeon64Expr(env, e->Iex.Binop.arg2); 2302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size = 0; 2303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NBinary(ARMneon_VRSQRTS, 2304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, argR, size, False)); 2305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 2306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2307436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 2308436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov // These 6 verified 18 Apr 2013 2309436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case Iop_InterleaveHI32x2: 2310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_InterleaveLO32x2: 2311436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case Iop_InterleaveOddLanes8x8: 2312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_InterleaveEvenLanes8x8: 2313436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case Iop_InterleaveOddLanes16x4: 2314436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case Iop_InterleaveEvenLanes16x4: { 2315436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov HReg rD = newVRegD(env); 2316436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov HReg rM = newVRegD(env); 2317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeon64Expr(env, e->Iex.Binop.arg1); 2318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeon64Expr(env, e->Iex.Binop.arg2); 2319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size; 2320436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov Bool resRd; // is the result in rD or rM ? 2321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (e->Iex.Binop.op) { 2322436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case Iop_InterleaveOddLanes8x8: resRd = False; size = 0; break; 2323436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case Iop_InterleaveEvenLanes8x8: resRd = True; size = 0; break; 2324436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case Iop_InterleaveOddLanes16x4: resRd = False; size = 1; break; 2325436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case Iop_InterleaveEvenLanes16x4: resRd = True; size = 1; break; 2326436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case Iop_InterleaveHI32x2: resRd = False; size = 2; break; 2327436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case Iop_InterleaveLO32x2: resRd = True; size = 2; break; 2328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: vassert(0); 2329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2330436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov addInstr(env, ARMInstr_NUnary(ARMneon_COPY, rM, argL, 4, False)); 2331436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov addInstr(env, ARMInstr_NUnary(ARMneon_COPY, rD, argR, 4, False)); 2332436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov addInstr(env, ARMInstr_NDual(ARMneon_TRN, rD, rM, size, False)); 2333436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov return resRd ? rD : rM; 2334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2335436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 2336436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov // These 4 verified 18 Apr 2013 2337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_InterleaveHI8x8: 2338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_InterleaveLO8x8: 2339436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case Iop_InterleaveHI16x4: 2340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_InterleaveLO16x4: { 2341436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov HReg rD = newVRegD(env); 2342436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov HReg rM = newVRegD(env); 2343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeon64Expr(env, e->Iex.Binop.arg1); 2344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeon64Expr(env, e->Iex.Binop.arg2); 2345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size; 2346436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov Bool resRd; // is the result in rD or rM ? 2347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (e->Iex.Binop.op) { 2348436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case Iop_InterleaveHI8x8: resRd = False; size = 0; break; 2349436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case Iop_InterleaveLO8x8: resRd = True; size = 0; break; 2350436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case Iop_InterleaveHI16x4: resRd = False; size = 1; break; 2351436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case Iop_InterleaveLO16x4: resRd = True; size = 1; break; 2352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: vassert(0); 2353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2354436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov addInstr(env, ARMInstr_NUnary(ARMneon_COPY, rM, argL, 4, False)); 2355436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov addInstr(env, ARMInstr_NUnary(ARMneon_COPY, rD, argR, 4, False)); 2356436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov addInstr(env, ARMInstr_NDual(ARMneon_ZIP, rD, rM, size, False)); 2357436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov return resRd ? rD : rM; 2358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2359436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 2360436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov // These 4 verified 18 Apr 2013 2361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CatOddLanes8x8: 2362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CatEvenLanes8x8: 2363436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case Iop_CatOddLanes16x4: 2364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CatEvenLanes16x4: { 2365436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov HReg rD = newVRegD(env); 2366436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov HReg rM = newVRegD(env); 2367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeon64Expr(env, e->Iex.Binop.arg1); 2368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeon64Expr(env, e->Iex.Binop.arg2); 2369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size; 2370436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov Bool resRd; // is the result in rD or rM ? 2371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (e->Iex.Binop.op) { 2372436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case Iop_CatOddLanes8x8: resRd = False; size = 0; break; 2373436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case Iop_CatEvenLanes8x8: resRd = True; size = 0; break; 2374436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case Iop_CatOddLanes16x4: resRd = False; size = 1; break; 2375436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case Iop_CatEvenLanes16x4: resRd = True; size = 1; break; 2376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: vassert(0); 2377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2378436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov addInstr(env, ARMInstr_NUnary(ARMneon_COPY, rM, argL, 4, False)); 2379436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov addInstr(env, ARMInstr_NUnary(ARMneon_COPY, rD, argR, 4, False)); 2380436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov addInstr(env, ARMInstr_NDual(ARMneon_UZP, rD, rM, size, False)); 2381436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov return resRd ? rD : rM; 2382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2383436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 2384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QAdd8Ux8: 2385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QAdd16Ux4: 2386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QAdd32Ux2: 2387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QAdd64Ux1: { 2388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegD(env); 2389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeon64Expr(env, e->Iex.Binop.arg1); 2390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeon64Expr(env, e->Iex.Binop.arg2); 2391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size; 2392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (e->Iex.Binop.op) { 2393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QAdd8Ux8: size = 0; break; 2394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QAdd16Ux4: size = 1; break; 2395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QAdd32Ux2: size = 2; break; 2396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QAdd64Ux1: size = 3; break; 2397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: vassert(0); 2398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NBinary(ARMneon_VQADDU, 2400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, argR, size, False)); 2401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 2402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QAdd8Sx8: 2404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QAdd16Sx4: 2405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QAdd32Sx2: 2406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QAdd64Sx1: { 2407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegD(env); 2408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeon64Expr(env, e->Iex.Binop.arg1); 2409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeon64Expr(env, e->Iex.Binop.arg2); 2410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size; 2411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (e->Iex.Binop.op) { 2412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QAdd8Sx8: size = 0; break; 2413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QAdd16Sx4: size = 1; break; 2414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QAdd32Sx2: size = 2; break; 2415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QAdd64Sx1: size = 3; break; 2416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: vassert(0); 2417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NBinary(ARMneon_VQADDS, 2419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, argR, size, False)); 2420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 2421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Sub8x8: 2423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Sub16x4: 2424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Sub32x2: 2425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Sub64: { 2426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegD(env); 2427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeon64Expr(env, e->Iex.Binop.arg1); 2428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeon64Expr(env, e->Iex.Binop.arg2); 2429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size; 2430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (e->Iex.Binop.op) { 2431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Sub8x8: size = 0; break; 2432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Sub16x4: size = 1; break; 2433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Sub32x2: size = 2; break; 2434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Sub64: size = 3; break; 2435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: vassert(0); 2436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NBinary(ARMneon_VSUB, 2438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, argR, size, False)); 2439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 2440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Sub32Fx2: { 2442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegD(env); 2443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeon64Expr(env, e->Iex.Binop.arg1); 2444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeon64Expr(env, e->Iex.Binop.arg2); 2445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size = 0; 2446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NBinary(ARMneon_VSUBFP, 2447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, argR, size, False)); 2448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 2449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QSub8Ux8: 2451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QSub16Ux4: 2452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QSub32Ux2: 2453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QSub64Ux1: { 2454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegD(env); 2455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeon64Expr(env, e->Iex.Binop.arg1); 2456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeon64Expr(env, e->Iex.Binop.arg2); 2457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size; 2458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (e->Iex.Binop.op) { 2459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QSub8Ux8: size = 0; break; 2460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QSub16Ux4: size = 1; break; 2461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QSub32Ux2: size = 2; break; 2462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QSub64Ux1: size = 3; break; 2463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: vassert(0); 2464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NBinary(ARMneon_VQSUBU, 2466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, argR, size, False)); 2467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 2468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QSub8Sx8: 2470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QSub16Sx4: 2471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QSub32Sx2: 2472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QSub64Sx1: { 2473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegD(env); 2474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeon64Expr(env, e->Iex.Binop.arg1); 2475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeon64Expr(env, e->Iex.Binop.arg2); 2476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size; 2477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (e->Iex.Binop.op) { 2478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QSub8Sx8: size = 0; break; 2479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QSub16Sx4: size = 1; break; 2480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QSub32Sx2: size = 2; break; 2481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QSub64Sx1: size = 3; break; 2482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: vassert(0); 2483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NBinary(ARMneon_VQSUBS, 2485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, argR, size, False)); 2486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 2487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Max8Ux8: 2489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Max16Ux4: 2490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Max32Ux2: { 2491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegD(env); 2492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeon64Expr(env, e->Iex.Binop.arg1); 2493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeon64Expr(env, e->Iex.Binop.arg2); 2494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size; 2495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (e->Iex.Binop.op) { 2496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Max8Ux8: size = 0; break; 2497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Max16Ux4: size = 1; break; 2498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Max32Ux2: size = 2; break; 2499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: vassert(0); 2500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NBinary(ARMneon_VMAXU, 2502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, argR, size, False)); 2503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 2504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Max8Sx8: 2506ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Max16Sx4: 2507ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Max32Sx2: { 2508ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegD(env); 2509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeon64Expr(env, e->Iex.Binop.arg1); 2510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeon64Expr(env, e->Iex.Binop.arg2); 2511ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size; 2512ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (e->Iex.Binop.op) { 2513ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Max8Sx8: size = 0; break; 2514ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Max16Sx4: size = 1; break; 2515ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Max32Sx2: size = 2; break; 2516ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: vassert(0); 2517ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NBinary(ARMneon_VMAXS, 2519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, argR, size, False)); 2520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 2521ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Min8Ux8: 2523ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Min16Ux4: 2524ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Min32Ux2: { 2525ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegD(env); 2526ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeon64Expr(env, e->Iex.Binop.arg1); 2527ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeon64Expr(env, e->Iex.Binop.arg2); 2528ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size; 2529ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (e->Iex.Binop.op) { 2530ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Min8Ux8: size = 0; break; 2531ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Min16Ux4: size = 1; break; 2532ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Min32Ux2: size = 2; break; 2533ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: vassert(0); 2534ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2535ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NBinary(ARMneon_VMINU, 2536ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, argR, size, False)); 2537ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 2538ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2539ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Min8Sx8: 2540ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Min16Sx4: 2541ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Min32Sx2: { 2542ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegD(env); 2543ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeon64Expr(env, e->Iex.Binop.arg1); 2544ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeon64Expr(env, e->Iex.Binop.arg2); 2545ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size; 2546ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (e->Iex.Binop.op) { 2547ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Min8Sx8: size = 0; break; 2548ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Min16Sx4: size = 1; break; 2549ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Min32Sx2: size = 2; break; 2550ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: vassert(0); 2551ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2552ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NBinary(ARMneon_VMINS, 2553ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, argR, size, False)); 2554ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 2555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Sar8x8: 2557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Sar16x4: 2558ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Sar32x2: { 2559ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegD(env); 2560ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeon64Expr(env, e->Iex.Binop.arg1); 2561ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeon64Expr(env, e->Iex.Binop.arg2); 2562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR2 = newVRegD(env); 2563ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg zero = newVRegD(env); 2564ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size; 2565ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (e->Iex.Binop.op) { 2566ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Sar8x8: size = 0; break; 2567ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Sar16x4: size = 1; break; 2568ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Sar32x2: size = 2; break; 2569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Sar64: size = 3; break; 2570ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: vassert(0); 2571ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2572ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NeonImm(zero, ARMNImm_TI(0,0))); 2573ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NBinary(ARMneon_VSUB, 2574ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown argR2, zero, argR, size, False)); 2575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NShift(ARMneon_VSAL, 2576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, argR2, size, False)); 2577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 2578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Sal8x8: 2580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Sal16x4: 2581ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Sal32x2: 2582ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Sal64x1: { 2583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegD(env); 2584ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeon64Expr(env, e->Iex.Binop.arg1); 2585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeon64Expr(env, e->Iex.Binop.arg2); 2586ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size; 2587ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (e->Iex.Binop.op) { 2588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Sal8x8: size = 0; break; 2589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Sal16x4: size = 1; break; 2590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Sal32x2: size = 2; break; 2591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Sal64x1: size = 3; break; 2592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: vassert(0); 2593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NShift(ARMneon_VSAL, 2595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, argR, size, False)); 2596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 2597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Shr8x8: 2599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Shr16x4: 2600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Shr32x2: { 2601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegD(env); 2602ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeon64Expr(env, e->Iex.Binop.arg1); 2603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeon64Expr(env, e->Iex.Binop.arg2); 2604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR2 = newVRegD(env); 2605ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg zero = newVRegD(env); 2606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size; 2607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (e->Iex.Binop.op) { 2608ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Shr8x8: size = 0; break; 2609ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Shr16x4: size = 1; break; 2610ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Shr32x2: size = 2; break; 2611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: vassert(0); 2612ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2613ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NeonImm(zero, ARMNImm_TI(0,0))); 2614ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NBinary(ARMneon_VSUB, 2615ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown argR2, zero, argR, size, False)); 2616ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NShift(ARMneon_VSHL, 2617ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, argR2, size, False)); 2618ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 2619ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2620ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Shl8x8: 2621ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Shl16x4: 2622ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Shl32x2: { 2623ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegD(env); 2624ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeon64Expr(env, e->Iex.Binop.arg1); 2625ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeon64Expr(env, e->Iex.Binop.arg2); 2626ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size; 2627ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (e->Iex.Binop.op) { 2628ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Shl8x8: size = 0; break; 2629ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Shl16x4: size = 1; break; 2630ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Shl32x2: size = 2; break; 2631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: vassert(0); 2632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2633ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NShift(ARMneon_VSHL, 2634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, argR, size, False)); 2635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 2636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QShl8x8: 2638ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QShl16x4: 2639ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QShl32x2: 2640ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QShl64x1: { 2641ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegD(env); 2642ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeon64Expr(env, e->Iex.Binop.arg1); 2643ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeon64Expr(env, e->Iex.Binop.arg2); 2644ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size; 2645ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (e->Iex.Binop.op) { 2646ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QShl8x8: size = 0; break; 2647ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QShl16x4: size = 1; break; 2648ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QShl32x2: size = 2; break; 2649ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QShl64x1: size = 3; break; 2650ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: vassert(0); 2651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2652ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NShift(ARMneon_VQSHL, 2653ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, argR, size, False)); 2654ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 2655ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2656ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QSal8x8: 2657ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QSal16x4: 2658ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QSal32x2: 2659ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QSal64x1: { 2660ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegD(env); 2661ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeon64Expr(env, e->Iex.Binop.arg1); 2662ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeon64Expr(env, e->Iex.Binop.arg2); 2663ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size; 2664ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (e->Iex.Binop.op) { 2665ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QSal8x8: size = 0; break; 2666ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QSal16x4: size = 1; break; 2667ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QSal32x2: size = 2; break; 2668ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QSal64x1: size = 3; break; 2669ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: vassert(0); 2670ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2671ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NShift(ARMneon_VQSAL, 2672ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, argR, size, False)); 2673ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 2674ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2675ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QShlN8x8: 2676ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QShlN16x4: 2677ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QShlN32x2: 2678ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QShlN64x1: { 2679ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegD(env); 2680ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeon64Expr(env, e->Iex.Binop.arg1); 2681ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size, imm; 2682ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->Iex.Binop.arg2->tag != Iex_Const || 2683ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown typeOfIRExpr(env->type_env, e->Iex.Binop.arg2) != Ity_I8) { 2684ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vpanic("ARM taget supports Iop_QShlNAxB with constant " 2685ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "second argument only\n"); 2686ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2687ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown imm = e->Iex.Binop.arg2->Iex.Const.con->Ico.U8; 2688ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (e->Iex.Binop.op) { 2689ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QShlN8x8: size = 8 | imm; break; 2690ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QShlN16x4: size = 16 | imm; break; 2691ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QShlN32x2: size = 32 | imm; break; 2692ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QShlN64x1: size = 64 | imm; break; 2693ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: vassert(0); 2694ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2695ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnary(ARMneon_VQSHLNUU, 2696ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, size, False)); 2697ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 2698ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2699ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QShlN8Sx8: 2700ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QShlN16Sx4: 2701ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QShlN32Sx2: 2702ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QShlN64Sx1: { 2703ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegD(env); 2704ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeon64Expr(env, e->Iex.Binop.arg1); 2705ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size, imm; 2706ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->Iex.Binop.arg2->tag != Iex_Const || 2707ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown typeOfIRExpr(env->type_env, e->Iex.Binop.arg2) != Ity_I8) { 2708ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vpanic("ARM taget supports Iop_QShlNAxB with constant " 2709ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "second argument only\n"); 2710ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2711ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown imm = e->Iex.Binop.arg2->Iex.Const.con->Ico.U8; 2712ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (e->Iex.Binop.op) { 2713ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QShlN8Sx8: size = 8 | imm; break; 2714ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QShlN16Sx4: size = 16 | imm; break; 2715ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QShlN32Sx2: size = 32 | imm; break; 2716ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QShlN64Sx1: size = 64 | imm; break; 2717ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: vassert(0); 2718ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2719ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnary(ARMneon_VQSHLNUS, 2720ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, size, False)); 2721ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 2722ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2723ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QSalN8x8: 2724ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QSalN16x4: 2725ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QSalN32x2: 2726ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QSalN64x1: { 2727ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegD(env); 2728ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeon64Expr(env, e->Iex.Binop.arg1); 2729ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size, imm; 2730ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->Iex.Binop.arg2->tag != Iex_Const || 2731ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown typeOfIRExpr(env->type_env, e->Iex.Binop.arg2) != Ity_I8) { 2732ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vpanic("ARM taget supports Iop_QShlNAxB with constant " 2733ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "second argument only\n"); 2734ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2735ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown imm = e->Iex.Binop.arg2->Iex.Const.con->Ico.U8; 2736ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (e->Iex.Binop.op) { 2737ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QSalN8x8: size = 8 | imm; break; 2738ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QSalN16x4: size = 16 | imm; break; 2739ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QSalN32x2: size = 32 | imm; break; 2740ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QSalN64x1: size = 64 | imm; break; 2741ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: vassert(0); 2742ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2743ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnary(ARMneon_VQSHLNSS, 2744ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, size, False)); 2745ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 2746ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2747ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_ShrN8x8: 2748ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_ShrN16x4: 2749ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_ShrN32x2: 2750ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Shr64: { 2751ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegD(env); 2752ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg tmp = newVRegD(env); 2753ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeon64Expr(env, e->Iex.Binop.arg1); 2754ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselIntExpr_R(env, e->Iex.Binop.arg2); 2755ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR2 = newVRegI(env); 2756ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size; 2757ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (e->Iex.Binop.op) { 2758ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_ShrN8x8: size = 0; break; 2759ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_ShrN16x4: size = 1; break; 2760ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_ShrN32x2: size = 2; break; 2761ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Shr64: size = 3; break; 2762ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: vassert(0); 2763ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2764ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_Unary(ARMun_NEG, argR2, argR)); 2765ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnary(ARMneon_DUP, tmp, argR2, 0, False)); 2766ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NShift(ARMneon_VSHL, 2767ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, tmp, size, False)); 2768ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 2769ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2770ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_ShlN8x8: 2771ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_ShlN16x4: 2772ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_ShlN32x2: 2773ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Shl64: { 2774ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegD(env); 2775ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg tmp = newVRegD(env); 2776ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeon64Expr(env, e->Iex.Binop.arg1); 2777436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /* special-case Shl64(x, imm8) since the Neon front 2778436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov end produces a lot of those for V{LD,ST}{1,2,3,4}. */ 2779436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov if (e->Iex.Binop.op == Iop_Shl64 2780436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov && e->Iex.Binop.arg2->tag == Iex_Const) { 2781436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov vassert(e->Iex.Binop.arg2->Iex.Const.con->tag == Ico_U8); 2782436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov Int nshift = e->Iex.Binop.arg2->Iex.Const.con->Ico.U8; 2783436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov if (nshift >= 1 && nshift <= 63) { 2784436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov addInstr(env, ARMInstr_NShl64(res, argL, nshift)); 2785436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov return res; 2786436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } 2787436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /* else fall through to general case */ 2788436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } 2789ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselIntExpr_R(env, e->Iex.Binop.arg2); 2790ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size; 2791ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (e->Iex.Binop.op) { 2792436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case Iop_ShlN8x8: size = 0; break; 2793ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_ShlN16x4: size = 1; break; 2794ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_ShlN32x2: size = 2; break; 2795436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case Iop_Shl64: size = 3; break; 2796ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: vassert(0); 2797ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2798436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov addInstr(env, ARMInstr_NUnary(ARMneon_DUP, 2799436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov tmp, argR, 0, False)); 2800ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NShift(ARMneon_VSHL, 2801ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, tmp, size, False)); 2802ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 2803ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2804ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_SarN8x8: 2805ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_SarN16x4: 2806ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_SarN32x2: 2807ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Sar64: { 2808ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegD(env); 2809ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg tmp = newVRegD(env); 2810ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeon64Expr(env, e->Iex.Binop.arg1); 2811ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselIntExpr_R(env, e->Iex.Binop.arg2); 2812ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR2 = newVRegI(env); 2813ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size; 2814ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (e->Iex.Binop.op) { 2815ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_SarN8x8: size = 0; break; 2816ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_SarN16x4: size = 1; break; 2817ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_SarN32x2: size = 2; break; 2818ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Sar64: size = 3; break; 2819ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: vassert(0); 2820ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2821ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_Unary(ARMun_NEG, argR2, argR)); 2822ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnary(ARMneon_DUP, tmp, argR2, 0, False)); 2823ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NShift(ARMneon_VSAL, 2824ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, tmp, size, False)); 2825ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 2826ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2827ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CmpGT8Ux8: 2828ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CmpGT16Ux4: 2829ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CmpGT32Ux2: { 2830ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegD(env); 2831ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeon64Expr(env, e->Iex.Binop.arg1); 2832ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeon64Expr(env, e->Iex.Binop.arg2); 2833ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size; 2834ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (e->Iex.Binop.op) { 2835ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CmpGT8Ux8: size = 0; break; 2836ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CmpGT16Ux4: size = 1; break; 2837ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CmpGT32Ux2: size = 2; break; 2838ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: vassert(0); 2839ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2840ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NBinary(ARMneon_VCGTU, 2841ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, argR, size, False)); 2842ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 2843ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2844ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CmpGT8Sx8: 2845ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CmpGT16Sx4: 2846ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CmpGT32Sx2: { 2847ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegD(env); 2848ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeon64Expr(env, e->Iex.Binop.arg1); 2849ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeon64Expr(env, e->Iex.Binop.arg2); 2850ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size; 2851ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (e->Iex.Binop.op) { 2852ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CmpGT8Sx8: size = 0; break; 2853ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CmpGT16Sx4: size = 1; break; 2854ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CmpGT32Sx2: size = 2; break; 2855ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: vassert(0); 2856ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2857ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NBinary(ARMneon_VCGTS, 2858ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, argR, size, False)); 2859ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 2860ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2861ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CmpEQ8x8: 2862ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CmpEQ16x4: 2863ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CmpEQ32x2: { 2864ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegD(env); 2865ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeon64Expr(env, e->Iex.Binop.arg1); 2866ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeon64Expr(env, e->Iex.Binop.arg2); 2867ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size; 2868ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (e->Iex.Binop.op) { 2869ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CmpEQ8x8: size = 0; break; 2870ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CmpEQ16x4: size = 1; break; 2871ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CmpEQ32x2: size = 2; break; 2872ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: vassert(0); 2873ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2874ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NBinary(ARMneon_VCEQ, 2875ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, argR, size, False)); 2876ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 2877ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2878ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Mul8x8: 2879ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Mul16x4: 2880ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Mul32x2: { 2881ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegD(env); 2882ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeon64Expr(env, e->Iex.Binop.arg1); 2883ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeon64Expr(env, e->Iex.Binop.arg2); 2884ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size = 0; 2885ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch(e->Iex.Binop.op) { 2886ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Mul8x8: size = 0; break; 2887ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Mul16x4: size = 1; break; 2888ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Mul32x2: size = 2; break; 2889ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: vassert(0); 2890ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2891ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NBinary(ARMneon_VMUL, 2892ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, argR, size, False)); 2893ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 2894ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2895ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Mul32Fx2: { 2896ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegD(env); 2897ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeon64Expr(env, e->Iex.Binop.arg1); 2898ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeon64Expr(env, e->Iex.Binop.arg2); 2899ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size = 0; 2900ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NBinary(ARMneon_VMULFP, 2901ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, argR, size, False)); 2902ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 2903ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2904ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QDMulHi16Sx4: 2905ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QDMulHi32Sx2: { 2906ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegD(env); 2907ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeon64Expr(env, e->Iex.Binop.arg1); 2908ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeon64Expr(env, e->Iex.Binop.arg2); 2909ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size = 0; 2910ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch(e->Iex.Binop.op) { 2911ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QDMulHi16Sx4: size = 1; break; 2912ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QDMulHi32Sx2: size = 2; break; 2913ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: vassert(0); 2914ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2915ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NBinary(ARMneon_VQDMULH, 2916ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, argR, size, False)); 2917ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 2918ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2919ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2920ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QRDMulHi16Sx4: 2921ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QRDMulHi32Sx2: { 2922ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegD(env); 2923ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeon64Expr(env, e->Iex.Binop.arg1); 2924ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeon64Expr(env, e->Iex.Binop.arg2); 2925ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size = 0; 2926ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch(e->Iex.Binop.op) { 2927ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QRDMulHi16Sx4: size = 1; break; 2928ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QRDMulHi32Sx2: size = 2; break; 2929ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: vassert(0); 2930ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2931ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NBinary(ARMneon_VQRDMULH, 2932ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, argR, size, False)); 2933ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 2934ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2935ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2936ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_PwAdd8x8: 2937ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_PwAdd16x4: 2938ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_PwAdd32x2: { 2939ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegD(env); 2940ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeon64Expr(env, e->Iex.Binop.arg1); 2941ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeon64Expr(env, e->Iex.Binop.arg2); 2942ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size = 0; 2943ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch(e->Iex.Binop.op) { 2944ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_PwAdd8x8: size = 0; break; 2945ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_PwAdd16x4: size = 1; break; 2946ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_PwAdd32x2: size = 2; break; 2947ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: vassert(0); 2948ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2949ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NBinary(ARMneon_VPADD, 2950ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, argR, size, False)); 2951ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 2952ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2953ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_PwAdd32Fx2: { 2954ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegD(env); 2955ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeon64Expr(env, e->Iex.Binop.arg1); 2956ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeon64Expr(env, e->Iex.Binop.arg2); 2957ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size = 0; 2958ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NBinary(ARMneon_VPADDFP, 2959ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, argR, size, False)); 2960ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 2961ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2962ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_PwMin8Ux8: 2963ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_PwMin16Ux4: 2964ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_PwMin32Ux2: { 2965ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegD(env); 2966ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeon64Expr(env, e->Iex.Binop.arg1); 2967ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeon64Expr(env, e->Iex.Binop.arg2); 2968ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size = 0; 2969ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch(e->Iex.Binop.op) { 2970ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_PwMin8Ux8: size = 0; break; 2971ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_PwMin16Ux4: size = 1; break; 2972ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_PwMin32Ux2: size = 2; break; 2973ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: vassert(0); 2974ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2975ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NBinary(ARMneon_VPMINU, 2976ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, argR, size, False)); 2977ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 2978ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2979ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_PwMin8Sx8: 2980ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_PwMin16Sx4: 2981ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_PwMin32Sx2: { 2982ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegD(env); 2983ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeon64Expr(env, e->Iex.Binop.arg1); 2984ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeon64Expr(env, e->Iex.Binop.arg2); 2985ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size = 0; 2986ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch(e->Iex.Binop.op) { 2987ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_PwMin8Sx8: size = 0; break; 2988ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_PwMin16Sx4: size = 1; break; 2989ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_PwMin32Sx2: size = 2; break; 2990ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: vassert(0); 2991ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2992ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NBinary(ARMneon_VPMINS, 2993ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, argR, size, False)); 2994ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 2995ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2996ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_PwMax8Ux8: 2997ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_PwMax16Ux4: 2998ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_PwMax32Ux2: { 2999ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegD(env); 3000ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeon64Expr(env, e->Iex.Binop.arg1); 3001ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeon64Expr(env, e->Iex.Binop.arg2); 3002ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size = 0; 3003ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch(e->Iex.Binop.op) { 3004ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_PwMax8Ux8: size = 0; break; 3005ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_PwMax16Ux4: size = 1; break; 3006ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_PwMax32Ux2: size = 2; break; 3007ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: vassert(0); 3008ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3009ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NBinary(ARMneon_VPMAXU, 3010ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, argR, size, False)); 3011ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 3012ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3013ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_PwMax8Sx8: 3014ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_PwMax16Sx4: 3015ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_PwMax32Sx2: { 3016ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegD(env); 3017ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeon64Expr(env, e->Iex.Binop.arg1); 3018ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeon64Expr(env, e->Iex.Binop.arg2); 3019ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size = 0; 3020ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch(e->Iex.Binop.op) { 3021ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_PwMax8Sx8: size = 0; break; 3022ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_PwMax16Sx4: size = 1; break; 3023ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_PwMax32Sx2: size = 2; break; 3024ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: vassert(0); 3025ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3026ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NBinary(ARMneon_VPMAXS, 3027ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, argR, size, False)); 3028ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 3029ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3030ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Perm8x8: { 3031ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegD(env); 3032ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeon64Expr(env, e->Iex.Binop.arg1); 3033ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeon64Expr(env, e->Iex.Binop.arg2); 3034ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NBinary(ARMneon_VTBL, 3035ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, argR, 0, False)); 3036ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 3037ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3038ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_PolynomialMul8x8: { 3039ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegD(env); 3040ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeon64Expr(env, e->Iex.Binop.arg1); 3041ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeon64Expr(env, e->Iex.Binop.arg2); 3042ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size = 0; 3043ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NBinary(ARMneon_VMULP, 3044ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, argR, size, False)); 3045ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 3046ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3047ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Max32Fx2: { 3048ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegD(env); 3049ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeon64Expr(env, e->Iex.Binop.arg1); 3050ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeon64Expr(env, e->Iex.Binop.arg2); 3051ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NBinary(ARMneon_VMAXF, 3052ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, argR, 2, False)); 3053ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 3054ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3055ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Min32Fx2: { 3056ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegD(env); 3057ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeon64Expr(env, e->Iex.Binop.arg1); 3058ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeon64Expr(env, e->Iex.Binop.arg2); 3059ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NBinary(ARMneon_VMINF, 3060ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, argR, 2, False)); 3061ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 3062ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3063ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_PwMax32Fx2: { 3064ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegD(env); 3065ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeon64Expr(env, e->Iex.Binop.arg1); 3066ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeon64Expr(env, e->Iex.Binop.arg2); 3067ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NBinary(ARMneon_VPMAXF, 3068ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, argR, 2, False)); 3069ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 3070ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3071ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_PwMin32Fx2: { 3072ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegD(env); 3073ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeon64Expr(env, e->Iex.Binop.arg1); 3074ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeon64Expr(env, e->Iex.Binop.arg2); 3075ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NBinary(ARMneon_VPMINF, 3076ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, argR, 2, False)); 3077ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 3078ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3079ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CmpGT32Fx2: { 3080ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegD(env); 3081ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeon64Expr(env, e->Iex.Binop.arg1); 3082ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeon64Expr(env, e->Iex.Binop.arg2); 3083ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NBinary(ARMneon_VCGTF, 3084ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, argR, 2, False)); 3085ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 3086ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3087ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CmpGE32Fx2: { 3088ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegD(env); 3089ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeon64Expr(env, e->Iex.Binop.arg1); 3090ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeon64Expr(env, e->Iex.Binop.arg2); 3091ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NBinary(ARMneon_VCGEF, 3092ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, argR, 2, False)); 3093ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 3094ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3095ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CmpEQ32Fx2: { 3096ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegD(env); 3097ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeon64Expr(env, e->Iex.Binop.arg1); 3098ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeon64Expr(env, e->Iex.Binop.arg2); 3099ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NBinary(ARMneon_VCEQF, 3100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, argR, 2, False)); 3101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 3102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_F32ToFixed32Ux2_RZ: 3104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_F32ToFixed32Sx2_RZ: 3105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Fixed32UToF32x2_RN: 3106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Fixed32SToF32x2_RN: { 3107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegD(env); 3108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg arg = iselNeon64Expr(env, e->Iex.Binop.arg1); 3109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ARMNeonUnOp op; 3110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt imm6; 3111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->Iex.Binop.arg2->tag != Iex_Const || 3112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown typeOfIRExpr(env->type_env, e->Iex.Binop.arg2) != Ity_I8) { 3113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vpanic("ARM supports FP <-> Fixed conversion with constant " 3114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "second argument less than 33 only\n"); 3115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown imm6 = e->Iex.Binop.arg2->Iex.Const.con->Ico.U8; 3117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert(imm6 <= 32 && imm6 > 0); 3118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown imm6 = 64 - imm6; 3119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch(e->Iex.Binop.op) { 3120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_F32ToFixed32Ux2_RZ: op = ARMneon_VCVTFtoFixedU; break; 3121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_F32ToFixed32Sx2_RZ: op = ARMneon_VCVTFtoFixedS; break; 3122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Fixed32UToF32x2_RN: op = ARMneon_VCVTFixedUtoF; break; 3123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Fixed32SToF32x2_RN: op = ARMneon_VCVTFixedStoF; break; 3124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: vassert(0); 3125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnary(op, res, arg, imm6, False)); 3127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 3128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* 3130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown FIXME: is this here or not? 3131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_VDup8x8: 3132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_VDup16x4: 3133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_VDup32x2: { 3134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegD(env); 3135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeon64Expr(env, e->Iex.Binop.arg1); 3136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt index; 3137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt imm4; 3138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size = 0; 3139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->Iex.Binop.arg2->tag != Iex_Const || 3140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown typeOfIRExpr(env->type_env, e->Iex.Binop.arg2) != Ity_I8) { 3141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vpanic("ARM supports Iop_VDup with constant " 3142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "second argument less than 16 only\n"); 3143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown index = e->Iex.Binop.arg2->Iex.Const.con->Ico.U8; 3145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch(e->Iex.Binop.op) { 3146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_VDup8x8: imm4 = (index << 1) + 1; break; 3147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_VDup16x4: imm4 = (index << 2) + 2; break; 3148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_VDup32x2: imm4 = (index << 3) + 4; break; 3149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: vassert(0); 3150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (imm4 >= 16) { 3152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vpanic("ARM supports Iop_VDup with constant " 3153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "second argument less than 16 only\n"); 3154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnary(ARMneon_VDUP, 3156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, imm4, False)); 3157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 3158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */ 3160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: 3161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 3162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* --------- UNARY ops --------- */ 3166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->tag == Iex_Unop) { 3167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (e->Iex.Unop.op) { 3168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3169436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /* 32Uto64 */ 3170436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case Iop_32Uto64: { 3171436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov HReg rLo = iselIntExpr_R(env, e->Iex.Unop.arg); 3172436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov HReg rHi = newVRegI(env); 3173436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov HReg res = newVRegD(env); 3174436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov addInstr(env, ARMInstr_Imm32(rHi, 0)); 3175436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov addInstr(env, ARMInstr_VXferD(True/*toD*/, res, rHi, rLo)); 3176436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov return res; 3177436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } 3178436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 3179436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /* 32Sto64 */ 3180436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case Iop_32Sto64: { 3181436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov HReg rLo = iselIntExpr_R(env, e->Iex.Unop.arg); 3182436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov HReg rHi = newVRegI(env); 3183436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov addInstr(env, mk_iMOVds_RR(rHi, rLo)); 3184436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov addInstr(env, ARMInstr_Shift(ARMsh_SAR, rHi, rHi, ARMRI5_I5(31))); 3185436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov HReg res = newVRegD(env); 3186436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov addInstr(env, ARMInstr_VXferD(True/*toD*/, res, rHi, rLo)); 3187436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov return res; 3188436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } 3189436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 3190436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /* The next 3 are pass-throughs */ 3191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* ReinterpF64asI64 */ 3192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_ReinterpF64asI64: 3193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Left64(e) */ 3194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Left64: 3195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* CmpwNEZ64(e) */ 3196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_1Sto64: { 3197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg rLo, rHi; 3198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegD(env); 3199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown iselInt64Expr(&rHi, &rLo, env, e); 3200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_VXferD(True/*toD*/, res, rHi, rLo)); 3201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 3202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3203436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 3204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Not64: { 3205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DECLARE_PATTERN(p_veqz_8x8); 3206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DECLARE_PATTERN(p_veqz_16x4); 3207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DECLARE_PATTERN(p_veqz_32x2); 3208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DECLARE_PATTERN(p_vcge_8sx8); 3209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DECLARE_PATTERN(p_vcge_16sx4); 3210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DECLARE_PATTERN(p_vcge_32sx2); 3211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DECLARE_PATTERN(p_vcge_8ux8); 3212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DECLARE_PATTERN(p_vcge_16ux4); 3213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DECLARE_PATTERN(p_vcge_32ux2); 3214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEFINE_PATTERN(p_veqz_8x8, 3215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown unop(Iop_Not64, unop(Iop_CmpNEZ8x8, bind(0)))); 3216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEFINE_PATTERN(p_veqz_16x4, 3217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown unop(Iop_Not64, unop(Iop_CmpNEZ16x4, bind(0)))); 3218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEFINE_PATTERN(p_veqz_32x2, 3219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown unop(Iop_Not64, unop(Iop_CmpNEZ32x2, bind(0)))); 3220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEFINE_PATTERN(p_vcge_8sx8, 3221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown unop(Iop_Not64, binop(Iop_CmpGT8Sx8, bind(1), bind(0)))); 3222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEFINE_PATTERN(p_vcge_16sx4, 3223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown unop(Iop_Not64, binop(Iop_CmpGT16Sx4, bind(1), bind(0)))); 3224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEFINE_PATTERN(p_vcge_32sx2, 3225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown unop(Iop_Not64, binop(Iop_CmpGT32Sx2, bind(1), bind(0)))); 3226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEFINE_PATTERN(p_vcge_8ux8, 3227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown unop(Iop_Not64, binop(Iop_CmpGT8Ux8, bind(1), bind(0)))); 3228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEFINE_PATTERN(p_vcge_16ux4, 3229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown unop(Iop_Not64, binop(Iop_CmpGT16Ux4, bind(1), bind(0)))); 3230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEFINE_PATTERN(p_vcge_32ux2, 3231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown unop(Iop_Not64, binop(Iop_CmpGT32Ux2, bind(1), bind(0)))); 3232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (matchIRExpr(&mi, p_veqz_8x8, e)) { 3233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegD(env); 3234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg arg = iselNeon64Expr(env, mi.bindee[0]); 3235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnary(ARMneon_EQZ, res, arg, 0, False)); 3236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 3237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else if (matchIRExpr(&mi, p_veqz_16x4, e)) { 3238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegD(env); 3239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg arg = iselNeon64Expr(env, mi.bindee[0]); 3240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnary(ARMneon_EQZ, res, arg, 1, False)); 3241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 3242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else if (matchIRExpr(&mi, p_veqz_32x2, e)) { 3243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegD(env); 3244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg arg = iselNeon64Expr(env, mi.bindee[0]); 3245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnary(ARMneon_EQZ, res, arg, 2, False)); 3246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 3247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else if (matchIRExpr(&mi, p_vcge_8sx8, e)) { 3248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegD(env); 3249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeon64Expr(env, mi.bindee[0]); 3250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeon64Expr(env, mi.bindee[1]); 3251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NBinary(ARMneon_VCGES, 3252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, argR, 0, False)); 3253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 3254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else if (matchIRExpr(&mi, p_vcge_16sx4, e)) { 3255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegD(env); 3256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeon64Expr(env, mi.bindee[0]); 3257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeon64Expr(env, mi.bindee[1]); 3258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NBinary(ARMneon_VCGES, 3259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, argR, 1, False)); 3260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 3261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else if (matchIRExpr(&mi, p_vcge_32sx2, e)) { 3262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegD(env); 3263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeon64Expr(env, mi.bindee[0]); 3264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeon64Expr(env, mi.bindee[1]); 3265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NBinary(ARMneon_VCGES, 3266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, argR, 2, False)); 3267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 3268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else if (matchIRExpr(&mi, p_vcge_8ux8, e)) { 3269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegD(env); 3270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeon64Expr(env, mi.bindee[0]); 3271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeon64Expr(env, mi.bindee[1]); 3272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NBinary(ARMneon_VCGEU, 3273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, argR, 0, False)); 3274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 3275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else if (matchIRExpr(&mi, p_vcge_16ux4, e)) { 3276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegD(env); 3277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeon64Expr(env, mi.bindee[0]); 3278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeon64Expr(env, mi.bindee[1]); 3279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NBinary(ARMneon_VCGEU, 3280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, argR, 1, False)); 3281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 3282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else if (matchIRExpr(&mi, p_vcge_32ux2, e)) { 3283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegD(env); 3284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeon64Expr(env, mi.bindee[0]); 3285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeon64Expr(env, mi.bindee[1]); 3286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NBinary(ARMneon_VCGEU, 3287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, argR, 2, False)); 3288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 3289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 3290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegD(env); 3291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg arg = iselNeon64Expr(env, e->Iex.Unop.arg); 3292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnary(ARMneon_NOT, res, arg, 4, False)); 3293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 3294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Dup8x8: 3297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Dup16x4: 3298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Dup32x2: { 3299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res, arg; 3300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size; 3301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DECLARE_PATTERN(p_vdup_8x8); 3302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DECLARE_PATTERN(p_vdup_16x4); 3303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DECLARE_PATTERN(p_vdup_32x2); 3304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEFINE_PATTERN(p_vdup_8x8, 3305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown unop(Iop_Dup8x8, binop(Iop_GetElem8x8, bind(0), bind(1)))); 3306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEFINE_PATTERN(p_vdup_16x4, 3307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown unop(Iop_Dup16x4, binop(Iop_GetElem16x4, bind(0), bind(1)))); 3308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEFINE_PATTERN(p_vdup_32x2, 3309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown unop(Iop_Dup32x2, binop(Iop_GetElem32x2, bind(0), bind(1)))); 3310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (matchIRExpr(&mi, p_vdup_8x8, e)) { 3311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt index; 3312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt imm4; 3313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (mi.bindee[1]->tag == Iex_Const && 3314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown typeOfIRExpr(env->type_env, mi.bindee[1]) == Ity_I8) { 3315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown index = mi.bindee[1]->Iex.Const.con->Ico.U8; 3316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown imm4 = (index << 1) + 1; 3317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (index < 8) { 3318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res = newVRegD(env); 3319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown arg = iselNeon64Expr(env, mi.bindee[0]); 3320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnaryS( 3321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ARMneon_VDUP, 3322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mkARMNRS(ARMNRS_Reg, res, 0), 3323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mkARMNRS(ARMNRS_Scalar, arg, index), 3324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown imm4, False 3325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown )); 3326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 3327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else if (matchIRExpr(&mi, p_vdup_16x4, e)) { 3330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt index; 3331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt imm4; 3332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (mi.bindee[1]->tag == Iex_Const && 3333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown typeOfIRExpr(env->type_env, mi.bindee[1]) == Ity_I8) { 3334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown index = mi.bindee[1]->Iex.Const.con->Ico.U8; 3335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown imm4 = (index << 2) + 2; 3336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (index < 4) { 3337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res = newVRegD(env); 3338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown arg = iselNeon64Expr(env, mi.bindee[0]); 3339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnaryS( 3340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ARMneon_VDUP, 3341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mkARMNRS(ARMNRS_Reg, res, 0), 3342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mkARMNRS(ARMNRS_Scalar, arg, index), 3343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown imm4, False 3344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown )); 3345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 3346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else if (matchIRExpr(&mi, p_vdup_32x2, e)) { 3349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt index; 3350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt imm4; 3351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (mi.bindee[1]->tag == Iex_Const && 3352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown typeOfIRExpr(env->type_env, mi.bindee[1]) == Ity_I8) { 3353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown index = mi.bindee[1]->Iex.Const.con->Ico.U8; 3354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown imm4 = (index << 3) + 4; 3355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (index < 2) { 3356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res = newVRegD(env); 3357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown arg = iselNeon64Expr(env, mi.bindee[0]); 3358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnaryS( 3359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ARMneon_VDUP, 3360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mkARMNRS(ARMNRS_Reg, res, 0), 3361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mkARMNRS(ARMNRS_Scalar, arg, index), 3362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown imm4, False 3363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown )); 3364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 3365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown arg = iselIntExpr_R(env, e->Iex.Unop.arg); 3369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res = newVRegD(env); 3370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (e->Iex.Unop.op) { 3371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Dup8x8: size = 0; break; 3372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Dup16x4: size = 1; break; 3373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Dup32x2: size = 2; break; 3374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: vassert(0); 3375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnary(ARMneon_DUP, res, arg, size, False)); 3377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 3378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Abs8x8: 3380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Abs16x4: 3381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Abs32x2: { 3382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegD(env); 3383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg arg = iselNeon64Expr(env, e->Iex.Unop.arg); 3384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size = 0; 3385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch(e->Iex.Binop.op) { 3386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Abs8x8: size = 0; break; 3387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Abs16x4: size = 1; break; 3388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Abs32x2: size = 2; break; 3389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: vassert(0); 3390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnary(ARMneon_ABS, res, arg, size, False)); 3392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 3393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Reverse64_8x8: 3395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Reverse64_16x4: 3396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Reverse64_32x2: { 3397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegD(env); 3398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg arg = iselNeon64Expr(env, e->Iex.Unop.arg); 3399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size = 0; 3400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch(e->Iex.Binop.op) { 3401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Reverse64_8x8: size = 0; break; 3402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Reverse64_16x4: size = 1; break; 3403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Reverse64_32x2: size = 2; break; 3404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: vassert(0); 3405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnary(ARMneon_REV64, 3407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, arg, size, False)); 3408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 3409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Reverse32_8x8: 3411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Reverse32_16x4: { 3412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegD(env); 3413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg arg = iselNeon64Expr(env, e->Iex.Unop.arg); 3414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size = 0; 3415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch(e->Iex.Binop.op) { 3416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Reverse32_8x8: size = 0; break; 3417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Reverse32_16x4: size = 1; break; 3418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: vassert(0); 3419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnary(ARMneon_REV32, 3421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, arg, size, False)); 3422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 3423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Reverse16_8x8: { 3425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegD(env); 3426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg arg = iselNeon64Expr(env, e->Iex.Unop.arg); 3427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size = 0; 3428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnary(ARMneon_REV16, 3429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, arg, size, False)); 3430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 3431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CmpwNEZ64: { 3433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg x_lsh = newVRegD(env); 3434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg x_rsh = newVRegD(env); 3435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg lsh_amt = newVRegD(env); 3436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg rsh_amt = newVRegD(env); 3437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg zero = newVRegD(env); 3438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg tmp = newVRegD(env); 3439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg tmp2 = newVRegD(env); 3440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegD(env); 3441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg x = newVRegD(env); 3442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg arg = iselNeon64Expr(env, e->Iex.Unop.arg); 3443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnary(ARMneon_EQZ, tmp2, arg, 2, False)); 3444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnary(ARMneon_NOT, x, tmp2, 4, False)); 3445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NeonImm(lsh_amt, ARMNImm_TI(0, 32))); 3446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NeonImm(zero, ARMNImm_TI(0, 0))); 3447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NBinary(ARMneon_VSUB, 3448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown rsh_amt, zero, lsh_amt, 2, False)); 3449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NShift(ARMneon_VSHL, 3450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown x_lsh, x, lsh_amt, 3, False)); 3451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NShift(ARMneon_VSHL, 3452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown x_rsh, x, rsh_amt, 3, False)); 3453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NBinary(ARMneon_VORR, 3454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tmp, x_lsh, x_rsh, 0, False)); 3455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NBinary(ARMneon_VORR, 3456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, tmp, x, 0, False)); 3457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 3458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CmpNEZ8x8: 3460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CmpNEZ16x4: 3461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CmpNEZ32x2: { 3462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegD(env); 3463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg tmp = newVRegD(env); 3464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg arg = iselNeon64Expr(env, e->Iex.Unop.arg); 3465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size; 3466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (e->Iex.Unop.op) { 3467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CmpNEZ8x8: size = 0; break; 3468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CmpNEZ16x4: size = 1; break; 3469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CmpNEZ32x2: size = 2; break; 3470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: vassert(0); 3471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnary(ARMneon_EQZ, tmp, arg, size, False)); 3473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnary(ARMneon_NOT, res, tmp, 4, False)); 3474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 3475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3476b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov case Iop_NarrowUn16to8x8: 3477b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov case Iop_NarrowUn32to16x4: 3478b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov case Iop_NarrowUn64to32x2: { 3479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegD(env); 3480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg arg = iselNeonExpr(env, e->Iex.Unop.arg); 3481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size = 0; 3482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch(e->Iex.Binop.op) { 3483b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov case Iop_NarrowUn16to8x8: size = 0; break; 3484b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov case Iop_NarrowUn32to16x4: size = 1; break; 3485b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov case Iop_NarrowUn64to32x2: size = 2; break; 3486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: vassert(0); 3487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnary(ARMneon_COPYN, 3489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, arg, size, False)); 3490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 3491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3492b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov case Iop_QNarrowUn16Sto8Sx8: 3493b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov case Iop_QNarrowUn32Sto16Sx4: 3494b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov case Iop_QNarrowUn64Sto32Sx2: { 3495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegD(env); 3496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg arg = iselNeonExpr(env, e->Iex.Unop.arg); 3497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size = 0; 3498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch(e->Iex.Binop.op) { 3499b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov case Iop_QNarrowUn16Sto8Sx8: size = 0; break; 3500b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov case Iop_QNarrowUn32Sto16Sx4: size = 1; break; 3501b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov case Iop_QNarrowUn64Sto32Sx2: size = 2; break; 3502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: vassert(0); 3503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnary(ARMneon_COPYQNSS, 3505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, arg, size, False)); 3506ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 3507ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3508b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov case Iop_QNarrowUn16Sto8Ux8: 3509b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov case Iop_QNarrowUn32Sto16Ux4: 3510b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov case Iop_QNarrowUn64Sto32Ux2: { 3511ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegD(env); 3512ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg arg = iselNeonExpr(env, e->Iex.Unop.arg); 3513ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size = 0; 3514ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch(e->Iex.Binop.op) { 3515b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov case Iop_QNarrowUn16Sto8Ux8: size = 0; break; 3516b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov case Iop_QNarrowUn32Sto16Ux4: size = 1; break; 3517b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov case Iop_QNarrowUn64Sto32Ux2: size = 2; break; 3518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: vassert(0); 3519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnary(ARMneon_COPYQNUS, 3521ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, arg, size, False)); 3522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 3523ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3524b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov case Iop_QNarrowUn16Uto8Ux8: 3525b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov case Iop_QNarrowUn32Uto16Ux4: 3526b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov case Iop_QNarrowUn64Uto32Ux2: { 3527ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegD(env); 3528ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg arg = iselNeonExpr(env, e->Iex.Unop.arg); 3529ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size = 0; 3530ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch(e->Iex.Binop.op) { 3531b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov case Iop_QNarrowUn16Uto8Ux8: size = 0; break; 3532b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov case Iop_QNarrowUn32Uto16Ux4: size = 1; break; 3533b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov case Iop_QNarrowUn64Uto32Ux2: size = 2; break; 3534ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: vassert(0); 3535ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3536ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnary(ARMneon_COPYQNUU, 3537ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, arg, size, False)); 3538ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 3539ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3540ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_PwAddL8Sx8: 3541ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_PwAddL16Sx4: 3542ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_PwAddL32Sx2: { 3543ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegD(env); 3544ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg arg = iselNeon64Expr(env, e->Iex.Unop.arg); 3545ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size = 0; 3546ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch(e->Iex.Binop.op) { 3547ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_PwAddL8Sx8: size = 0; break; 3548ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_PwAddL16Sx4: size = 1; break; 3549ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_PwAddL32Sx2: size = 2; break; 3550ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: vassert(0); 3551ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3552ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnary(ARMneon_PADDLS, 3553ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, arg, size, False)); 3554ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 3555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_PwAddL8Ux8: 3557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_PwAddL16Ux4: 3558ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_PwAddL32Ux2: { 3559ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegD(env); 3560ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg arg = iselNeon64Expr(env, e->Iex.Unop.arg); 3561ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size = 0; 3562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch(e->Iex.Binop.op) { 3563ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_PwAddL8Ux8: size = 0; break; 3564ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_PwAddL16Ux4: size = 1; break; 3565ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_PwAddL32Ux2: size = 2; break; 3566ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: vassert(0); 3567ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3568ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnary(ARMneon_PADDLU, 3569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, arg, size, False)); 3570ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 3571ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3572ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Cnt8x8: { 3573ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegD(env); 3574ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg arg = iselNeon64Expr(env, e->Iex.Unop.arg); 3575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size = 0; 3576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnary(ARMneon_CNT, 3577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, arg, size, False)); 3578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 3579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Clz8Sx8: 3581ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Clz16Sx4: 3582ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Clz32Sx2: { 3583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegD(env); 3584ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg arg = iselNeon64Expr(env, e->Iex.Unop.arg); 3585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size = 0; 3586ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch(e->Iex.Binop.op) { 3587ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Clz8Sx8: size = 0; break; 3588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Clz16Sx4: size = 1; break; 3589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Clz32Sx2: size = 2; break; 3590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: vassert(0); 3591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnary(ARMneon_CLZ, 3593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, arg, size, False)); 3594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 3595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Cls8Sx8: 3597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Cls16Sx4: 3598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Cls32Sx2: { 3599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegD(env); 3600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg arg = iselNeon64Expr(env, e->Iex.Unop.arg); 3601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size = 0; 3602ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch(e->Iex.Binop.op) { 3603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Cls8Sx8: size = 0; break; 3604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Cls16Sx4: size = 1; break; 3605ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Cls32Sx2: size = 2; break; 3606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: vassert(0); 3607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3608ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnary(ARMneon_CLS, 3609ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, arg, size, False)); 3610ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 3611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3612ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_FtoI32Sx2_RZ: { 3613ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegD(env); 3614ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg arg = iselNeon64Expr(env, e->Iex.Unop.arg); 3615ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnary(ARMneon_VCVTFtoS, 3616ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, arg, 2, False)); 3617ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 3618ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3619ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_FtoI32Ux2_RZ: { 3620ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegD(env); 3621ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg arg = iselNeon64Expr(env, e->Iex.Unop.arg); 3622ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnary(ARMneon_VCVTFtoU, 3623ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, arg, 2, False)); 3624ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 3625ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3626ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_I32StoFx2: { 3627ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegD(env); 3628ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg arg = iselNeon64Expr(env, e->Iex.Unop.arg); 3629ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnary(ARMneon_VCVTStoF, 3630ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, arg, 2, False)); 3631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 3632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3633ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_I32UtoFx2: { 3634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegD(env); 3635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg arg = iselNeon64Expr(env, e->Iex.Unop.arg); 3636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnary(ARMneon_VCVTUtoF, 3637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, arg, 2, False)); 3638ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 3639ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3640ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_F32toF16x4: { 3641ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegD(env); 3642ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg arg = iselNeonExpr(env, e->Iex.Unop.arg); 3643ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnary(ARMneon_VCVTF32toF16, 3644ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, arg, 2, False)); 3645ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 3646ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3647ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Recip32Fx2: { 3648ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegD(env); 3649ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeon64Expr(env, e->Iex.Binop.arg1); 3650ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnary(ARMneon_VRECIPF, 3651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, 0, False)); 3652ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 3653ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3654ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Recip32x2: { 3655ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegD(env); 3656ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeon64Expr(env, e->Iex.Binop.arg1); 3657ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnary(ARMneon_VRECIP, 3658ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, 0, False)); 3659ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 3660ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3661ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Abs32Fx2: { 3662ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DECLARE_PATTERN(p_vabd_32fx2); 3663ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEFINE_PATTERN(p_vabd_32fx2, 3664ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown unop(Iop_Abs32Fx2, 3665ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown binop(Iop_Sub32Fx2, 3666ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown bind(0), 3667ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown bind(1)))); 3668ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (matchIRExpr(&mi, p_vabd_32fx2, e)) { 3669ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegD(env); 3670ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeon64Expr(env, mi.bindee[0]); 3671ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeon64Expr(env, mi.bindee[1]); 3672ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NBinary(ARMneon_VABDFP, 3673ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, argR, 0, False)); 3674ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 3675ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 3676ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegD(env); 3677ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg arg = iselNeon64Expr(env, e->Iex.Unop.arg); 3678ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnary(ARMneon_VABSFP, 3679ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, arg, 0, False)); 3680ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 3681ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3682ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3683ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Rsqrte32Fx2: { 3684ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegD(env); 3685ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg arg = iselNeon64Expr(env, e->Iex.Unop.arg); 3686ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnary(ARMneon_VRSQRTEFP, 3687ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, arg, 0, False)); 3688ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 3689ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3690ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Rsqrte32x2: { 3691ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegD(env); 3692ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg arg = iselNeon64Expr(env, e->Iex.Unop.arg); 3693ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnary(ARMneon_VRSQRTE, 3694ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, arg, 0, False)); 3695ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 3696ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3697ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Neg32Fx2: { 3698ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegD(env); 3699ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg arg = iselNeon64Expr(env, e->Iex.Unop.arg); 3700ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnary(ARMneon_VNEGF, 3701ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, arg, 0, False)); 3702ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 3703ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3704ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: 3705ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 3706ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3707ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } /* if (e->tag == Iex_Unop) */ 3708ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3709ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->tag == Iex_Triop) { 3710663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng IRTriop *triop = e->Iex.Triop.details; 3711663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 3712663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng switch (triop->op) { 3713ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Extract64: { 3714ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegD(env); 3715663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng HReg argL = iselNeon64Expr(env, triop->arg1); 3716663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng HReg argR = iselNeon64Expr(env, triop->arg2); 3717ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt imm4; 3718663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng if (triop->arg3->tag != Iex_Const || 3719663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng typeOfIRExpr(env->type_env, triop->arg3) != Ity_I8) { 3720ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vpanic("ARM target supports Iop_Extract64 with constant " 3721ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "third argument less than 16 only\n"); 3722ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3723663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng imm4 = triop->arg3->Iex.Const.con->Ico.U8; 3724ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (imm4 >= 8) { 3725ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vpanic("ARM target supports Iop_Extract64 with constant " 3726ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "third argument less than 16 only\n"); 3727ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3728ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NBinary(ARMneon_VEXT, 3729ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, argR, imm4, False)); 3730ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 3731ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3732ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_SetElem8x8: 3733ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_SetElem16x4: 3734ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_SetElem32x2: { 3735ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegD(env); 3736663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng HReg dreg = iselNeon64Expr(env, triop->arg1); 3737663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng HReg arg = iselIntExpr_R(env, triop->arg3); 3738ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt index, size; 3739663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng if (triop->arg2->tag != Iex_Const || 3740663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng typeOfIRExpr(env->type_env, triop->arg2) != Ity_I8) { 3741ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vpanic("ARM target supports SetElem with constant " 3742ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "second argument only\n"); 3743ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3744663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng index = triop->arg2->Iex.Const.con->Ico.U8; 3745663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng switch (triop->op) { 3746ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_SetElem8x8: vassert(index < 8); size = 0; break; 3747ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_SetElem16x4: vassert(index < 4); size = 1; break; 3748ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_SetElem32x2: vassert(index < 2); size = 2; break; 3749ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: vassert(0); 3750ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3751ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnary(ARMneon_COPY, res, dreg, 4, False)); 3752ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnaryS(ARMneon_SETELEM, 3753ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mkARMNRS(ARMNRS_Scalar, res, index), 3754ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mkARMNRS(ARMNRS_Reg, arg, 0), 3755ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown size, False)); 3756ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 3757ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3758ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: 3759ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 3760ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3761ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3762ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3763ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* --------- MULTIPLEX --------- */ 3764436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov if (e->tag == Iex_ITE) { // VFD 3765ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg rLo, rHi; 3766ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegD(env); 3767ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown iselInt64Expr(&rHi, &rLo, env, e); 3768ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_VXferD(True/*toD*/, res, rHi, rLo)); 3769ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 3770ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3771ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3772ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ppIRExpr(e); 3773ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vpanic("iselNeon64Expr"); 3774ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 3775ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3776ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic HReg iselNeonExpr ( ISelEnv* env, IRExpr* e ) 3777ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 3778ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg r = iselNeonExpr_wrk( env, e ); 3779ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert(hregClass(r) == HRcVec128); 3780ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert(hregIsVirtual(r)); 3781ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return r; 3782ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 3783ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3784ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* DO NOT CALL THIS DIRECTLY */ 3785ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic HReg iselNeonExpr_wrk ( ISelEnv* env, IRExpr* e ) 3786ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 3787ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRType ty = typeOfIRExpr(env->type_env, e); 3788ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown MatchInfo mi; 3789ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert(e); 3790ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert(ty == Ity_V128); 3791ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3792ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->tag == Iex_RdTmp) { 3793ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return lookupIRTemp(env, e->Iex.RdTmp.tmp); 3794ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3795ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3796ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->tag == Iex_Const) { 3797ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* At the moment there should be no 128-bit constants in IR for ARM 3798ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown generated during disassemble. They are represented as Iop_64HLtoV128 3799ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown binary operation and are handled among binary ops. */ 3800ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* But zero can be created by valgrind internal optimizer */ 3801436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov if (e->Iex.Const.con->Ico.V128 == 0x0000) { 3802436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov HReg res = newVRegV(env); 3803436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov addInstr(env, ARMInstr_NeonImm(res, ARMNImm_TI(6, 0))); 3804436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov return res; 3805436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } 3806436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov if (e->Iex.Const.con->Ico.V128 == 0xFFFF) { 3807ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegV(env); 3808436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov addInstr(env, ARMInstr_NeonImm(res, ARMNImm_TI(6, 255))); 3809ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 3810ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3811ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ppIRExpr(e); 3812ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vpanic("128-bit constant is not implemented"); 3813ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3814ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3815ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->tag == Iex_Load) { 3816ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegV(env); 3817ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ARMAModeN* am = iselIntExpr_AModeN(env, e->Iex.Load.addr); 3818ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert(ty == Ity_V128); 3819ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NLdStQ(True, res, am)); 3820ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 3821ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3822ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3823ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->tag == Iex_Get) { 3824ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg addr = newVRegI(env); 3825ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegV(env); 3826ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert(ty == Ity_V128); 3827ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_Add32(addr, hregARM_R8(), e->Iex.Get.offset)); 3828ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NLdStQ(True, res, mkARMAModeN_R(addr))); 3829ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 3830ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3831ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3832ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->tag == Iex_Unop) { 3833ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (e->Iex.Unop.op) { 3834ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_NotV128: { 3835ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DECLARE_PATTERN(p_veqz_8x16); 3836ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DECLARE_PATTERN(p_veqz_16x8); 3837ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DECLARE_PATTERN(p_veqz_32x4); 3838ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DECLARE_PATTERN(p_vcge_8sx16); 3839ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DECLARE_PATTERN(p_vcge_16sx8); 3840ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DECLARE_PATTERN(p_vcge_32sx4); 3841ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DECLARE_PATTERN(p_vcge_8ux16); 3842ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DECLARE_PATTERN(p_vcge_16ux8); 3843ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DECLARE_PATTERN(p_vcge_32ux4); 3844ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEFINE_PATTERN(p_veqz_8x16, 3845ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown unop(Iop_NotV128, unop(Iop_CmpNEZ8x16, bind(0)))); 3846ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEFINE_PATTERN(p_veqz_16x8, 3847ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown unop(Iop_NotV128, unop(Iop_CmpNEZ16x8, bind(0)))); 3848ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEFINE_PATTERN(p_veqz_32x4, 3849ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown unop(Iop_NotV128, unop(Iop_CmpNEZ32x4, bind(0)))); 3850ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEFINE_PATTERN(p_vcge_8sx16, 3851ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown unop(Iop_NotV128, binop(Iop_CmpGT8Sx16, bind(1), bind(0)))); 3852ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEFINE_PATTERN(p_vcge_16sx8, 3853ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown unop(Iop_NotV128, binop(Iop_CmpGT16Sx8, bind(1), bind(0)))); 3854ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEFINE_PATTERN(p_vcge_32sx4, 3855ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown unop(Iop_NotV128, binop(Iop_CmpGT32Sx4, bind(1), bind(0)))); 3856ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEFINE_PATTERN(p_vcge_8ux16, 3857ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown unop(Iop_NotV128, binop(Iop_CmpGT8Ux16, bind(1), bind(0)))); 3858ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEFINE_PATTERN(p_vcge_16ux8, 3859ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown unop(Iop_NotV128, binop(Iop_CmpGT16Ux8, bind(1), bind(0)))); 3860ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEFINE_PATTERN(p_vcge_32ux4, 3861ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown unop(Iop_NotV128, binop(Iop_CmpGT32Ux4, bind(1), bind(0)))); 3862ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (matchIRExpr(&mi, p_veqz_8x16, e)) { 3863ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegV(env); 3864ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg arg = iselNeonExpr(env, mi.bindee[0]); 3865ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnary(ARMneon_EQZ, res, arg, 0, True)); 3866ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 3867ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else if (matchIRExpr(&mi, p_veqz_16x8, e)) { 3868ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegV(env); 3869ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg arg = iselNeonExpr(env, mi.bindee[0]); 3870ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnary(ARMneon_EQZ, res, arg, 1, True)); 3871ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 3872ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else if (matchIRExpr(&mi, p_veqz_32x4, e)) { 3873ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegV(env); 3874ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg arg = iselNeonExpr(env, mi.bindee[0]); 3875ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnary(ARMneon_EQZ, res, arg, 2, True)); 3876ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 3877ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else if (matchIRExpr(&mi, p_vcge_8sx16, e)) { 3878ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegV(env); 3879ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeonExpr(env, mi.bindee[0]); 3880ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeonExpr(env, mi.bindee[1]); 3881ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NBinary(ARMneon_VCGES, 3882ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, argR, 0, True)); 3883ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 3884ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else if (matchIRExpr(&mi, p_vcge_16sx8, e)) { 3885ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegV(env); 3886ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeonExpr(env, mi.bindee[0]); 3887ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeonExpr(env, mi.bindee[1]); 3888ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NBinary(ARMneon_VCGES, 3889ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, argR, 1, True)); 3890ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 3891ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else if (matchIRExpr(&mi, p_vcge_32sx4, e)) { 3892ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegV(env); 3893ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeonExpr(env, mi.bindee[0]); 3894ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeonExpr(env, mi.bindee[1]); 3895ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NBinary(ARMneon_VCGES, 3896ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, argR, 2, True)); 3897ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 3898ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else if (matchIRExpr(&mi, p_vcge_8ux16, e)) { 3899ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegV(env); 3900ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeonExpr(env, mi.bindee[0]); 3901ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeonExpr(env, mi.bindee[1]); 3902ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NBinary(ARMneon_VCGEU, 3903ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, argR, 0, True)); 3904ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 3905ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else if (matchIRExpr(&mi, p_vcge_16ux8, e)) { 3906ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegV(env); 3907ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeonExpr(env, mi.bindee[0]); 3908ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeonExpr(env, mi.bindee[1]); 3909ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NBinary(ARMneon_VCGEU, 3910ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, argR, 1, True)); 3911ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 3912ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else if (matchIRExpr(&mi, p_vcge_32ux4, e)) { 3913ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegV(env); 3914ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeonExpr(env, mi.bindee[0]); 3915ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeonExpr(env, mi.bindee[1]); 3916ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NBinary(ARMneon_VCGEU, 3917ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, argR, 2, True)); 3918ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 3919ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 3920ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegV(env); 3921ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg arg = iselNeonExpr(env, e->Iex.Unop.arg); 3922ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnary(ARMneon_NOT, res, arg, 4, True)); 3923ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 3924ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3925ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3926ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Dup8x16: 3927ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Dup16x8: 3928ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Dup32x4: { 3929ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res, arg; 3930ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size; 3931ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DECLARE_PATTERN(p_vdup_8x16); 3932ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DECLARE_PATTERN(p_vdup_16x8); 3933ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DECLARE_PATTERN(p_vdup_32x4); 3934ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEFINE_PATTERN(p_vdup_8x16, 3935ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown unop(Iop_Dup8x16, binop(Iop_GetElem8x8, bind(0), bind(1)))); 3936ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEFINE_PATTERN(p_vdup_16x8, 3937ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown unop(Iop_Dup16x8, binop(Iop_GetElem16x4, bind(0), bind(1)))); 3938ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEFINE_PATTERN(p_vdup_32x4, 3939ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown unop(Iop_Dup32x4, binop(Iop_GetElem32x2, bind(0), bind(1)))); 3940ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (matchIRExpr(&mi, p_vdup_8x16, e)) { 3941ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt index; 3942ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt imm4; 3943ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (mi.bindee[1]->tag == Iex_Const && 3944ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown typeOfIRExpr(env->type_env, mi.bindee[1]) == Ity_I8) { 3945ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown index = mi.bindee[1]->Iex.Const.con->Ico.U8; 3946ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown imm4 = (index << 1) + 1; 3947ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (index < 8) { 3948ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res = newVRegV(env); 3949ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown arg = iselNeon64Expr(env, mi.bindee[0]); 3950ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnaryS( 3951ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ARMneon_VDUP, 3952ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mkARMNRS(ARMNRS_Reg, res, 0), 3953ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mkARMNRS(ARMNRS_Scalar, arg, index), 3954ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown imm4, True 3955ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown )); 3956ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 3957ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3958ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3959ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else if (matchIRExpr(&mi, p_vdup_16x8, e)) { 3960ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt index; 3961ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt imm4; 3962ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (mi.bindee[1]->tag == Iex_Const && 3963ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown typeOfIRExpr(env->type_env, mi.bindee[1]) == Ity_I8) { 3964ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown index = mi.bindee[1]->Iex.Const.con->Ico.U8; 3965ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown imm4 = (index << 2) + 2; 3966ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (index < 4) { 3967ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res = newVRegV(env); 3968ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown arg = iselNeon64Expr(env, mi.bindee[0]); 3969ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnaryS( 3970ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ARMneon_VDUP, 3971ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mkARMNRS(ARMNRS_Reg, res, 0), 3972ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mkARMNRS(ARMNRS_Scalar, arg, index), 3973ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown imm4, True 3974ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown )); 3975ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 3976ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3977ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3978ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else if (matchIRExpr(&mi, p_vdup_32x4, e)) { 3979ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt index; 3980ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt imm4; 3981ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (mi.bindee[1]->tag == Iex_Const && 3982ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown typeOfIRExpr(env->type_env, mi.bindee[1]) == Ity_I8) { 3983ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown index = mi.bindee[1]->Iex.Const.con->Ico.U8; 3984ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown imm4 = (index << 3) + 4; 3985ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (index < 2) { 3986ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res = newVRegV(env); 3987ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown arg = iselNeon64Expr(env, mi.bindee[0]); 3988ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnaryS( 3989ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ARMneon_VDUP, 3990ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mkARMNRS(ARMNRS_Reg, res, 0), 3991ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mkARMNRS(ARMNRS_Scalar, arg, index), 3992ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown imm4, True 3993ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown )); 3994ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 3995ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3996ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3997ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3998ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown arg = iselIntExpr_R(env, e->Iex.Unop.arg); 3999ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res = newVRegV(env); 4000ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (e->Iex.Unop.op) { 4001ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Dup8x16: size = 0; break; 4002ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Dup16x8: size = 1; break; 4003ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Dup32x4: size = 2; break; 4004ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: vassert(0); 4005ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4006ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnary(ARMneon_DUP, res, arg, size, True)); 4007ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 4008ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4009ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Abs8x16: 4010ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Abs16x8: 4011ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Abs32x4: { 4012ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegV(env); 4013ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg arg = iselNeonExpr(env, e->Iex.Unop.arg); 4014ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size = 0; 4015ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch(e->Iex.Binop.op) { 4016ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Abs8x16: size = 0; break; 4017ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Abs16x8: size = 1; break; 4018ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Abs32x4: size = 2; break; 4019ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: vassert(0); 4020ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4021ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnary(ARMneon_ABS, res, arg, size, True)); 4022ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 4023ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4024ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Reverse64_8x16: 4025ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Reverse64_16x8: 4026ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Reverse64_32x4: { 4027ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegV(env); 4028ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg arg = iselNeonExpr(env, e->Iex.Unop.arg); 4029ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size = 0; 4030ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch(e->Iex.Binop.op) { 4031ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Reverse64_8x16: size = 0; break; 4032ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Reverse64_16x8: size = 1; break; 4033ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Reverse64_32x4: size = 2; break; 4034ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: vassert(0); 4035ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4036ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnary(ARMneon_REV64, 4037ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, arg, size, True)); 4038ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 4039ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4040ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Reverse32_8x16: 4041ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Reverse32_16x8: { 4042ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegV(env); 4043ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg arg = iselNeonExpr(env, e->Iex.Unop.arg); 4044ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size = 0; 4045ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch(e->Iex.Binop.op) { 4046ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Reverse32_8x16: size = 0; break; 4047ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Reverse32_16x8: size = 1; break; 4048ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: vassert(0); 4049ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4050ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnary(ARMneon_REV32, 4051ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, arg, size, True)); 4052ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 4053ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4054ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Reverse16_8x16: { 4055ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegV(env); 4056ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg arg = iselNeonExpr(env, e->Iex.Unop.arg); 4057ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size = 0; 4058ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnary(ARMneon_REV16, 4059ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, arg, size, True)); 4060ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 4061ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4062ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CmpNEZ64x2: { 4063ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg x_lsh = newVRegV(env); 4064ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg x_rsh = newVRegV(env); 4065ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg lsh_amt = newVRegV(env); 4066ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg rsh_amt = newVRegV(env); 4067ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg zero = newVRegV(env); 4068ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg tmp = newVRegV(env); 4069ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg tmp2 = newVRegV(env); 4070ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegV(env); 4071ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg x = newVRegV(env); 4072ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg arg = iselNeonExpr(env, e->Iex.Unop.arg); 4073ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnary(ARMneon_EQZ, tmp2, arg, 2, True)); 4074ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnary(ARMneon_NOT, x, tmp2, 4, True)); 4075ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NeonImm(lsh_amt, ARMNImm_TI(0, 32))); 4076ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NeonImm(zero, ARMNImm_TI(0, 0))); 4077ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NBinary(ARMneon_VSUB, 4078ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown rsh_amt, zero, lsh_amt, 2, True)); 4079ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NShift(ARMneon_VSHL, 4080ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown x_lsh, x, lsh_amt, 3, True)); 4081ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NShift(ARMneon_VSHL, 4082ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown x_rsh, x, rsh_amt, 3, True)); 4083ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NBinary(ARMneon_VORR, 4084ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tmp, x_lsh, x_rsh, 0, True)); 4085ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NBinary(ARMneon_VORR, 4086ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, tmp, x, 0, True)); 4087ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 4088ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4089ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CmpNEZ8x16: 4090ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CmpNEZ16x8: 4091ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CmpNEZ32x4: { 4092ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegV(env); 4093ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg tmp = newVRegV(env); 4094ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg arg = iselNeonExpr(env, e->Iex.Unop.arg); 4095ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size; 4096ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (e->Iex.Unop.op) { 4097ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CmpNEZ8x16: size = 0; break; 4098ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CmpNEZ16x8: size = 1; break; 4099ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CmpNEZ32x4: size = 2; break; 4100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: vassert(0); 4101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnary(ARMneon_EQZ, tmp, arg, size, True)); 4103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnary(ARMneon_NOT, res, tmp, 4, True)); 4104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 4105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4106b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov case Iop_Widen8Uto16x8: 4107b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov case Iop_Widen16Uto32x4: 4108b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov case Iop_Widen32Uto64x2: { 4109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegV(env); 4110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg arg = iselNeon64Expr(env, e->Iex.Unop.arg); 4111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size; 4112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (e->Iex.Unop.op) { 4113b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov case Iop_Widen8Uto16x8: size = 0; break; 4114b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov case Iop_Widen16Uto32x4: size = 1; break; 4115b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov case Iop_Widen32Uto64x2: size = 2; break; 4116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: vassert(0); 4117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnary(ARMneon_COPYLU, 4119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, arg, size, True)); 4120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 4121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4122b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov case Iop_Widen8Sto16x8: 4123b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov case Iop_Widen16Sto32x4: 4124b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov case Iop_Widen32Sto64x2: { 4125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegV(env); 4126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg arg = iselNeon64Expr(env, e->Iex.Unop.arg); 4127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size; 4128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (e->Iex.Unop.op) { 4129b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov case Iop_Widen8Sto16x8: size = 0; break; 4130b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov case Iop_Widen16Sto32x4: size = 1; break; 4131b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov case Iop_Widen32Sto64x2: size = 2; break; 4132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: vassert(0); 4133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnary(ARMneon_COPYLS, 4135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, arg, size, True)); 4136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 4137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_PwAddL8Sx16: 4139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_PwAddL16Sx8: 4140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_PwAddL32Sx4: { 4141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegV(env); 4142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg arg = iselNeonExpr(env, e->Iex.Unop.arg); 4143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size = 0; 4144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch(e->Iex.Binop.op) { 4145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_PwAddL8Sx16: size = 0; break; 4146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_PwAddL16Sx8: size = 1; break; 4147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_PwAddL32Sx4: size = 2; break; 4148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: vassert(0); 4149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnary(ARMneon_PADDLS, 4151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, arg, size, True)); 4152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 4153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_PwAddL8Ux16: 4155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_PwAddL16Ux8: 4156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_PwAddL32Ux4: { 4157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegV(env); 4158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg arg = iselNeonExpr(env, e->Iex.Unop.arg); 4159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size = 0; 4160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch(e->Iex.Binop.op) { 4161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_PwAddL8Ux16: size = 0; break; 4162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_PwAddL16Ux8: size = 1; break; 4163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_PwAddL32Ux4: size = 2; break; 4164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: vassert(0); 4165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnary(ARMneon_PADDLU, 4167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, arg, size, True)); 4168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 4169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Cnt8x16: { 4171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegV(env); 4172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg arg = iselNeonExpr(env, e->Iex.Unop.arg); 4173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size = 0; 4174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnary(ARMneon_CNT, res, arg, size, True)); 4175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 4176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Clz8Sx16: 4178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Clz16Sx8: 4179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Clz32Sx4: { 4180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegV(env); 4181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg arg = iselNeonExpr(env, e->Iex.Unop.arg); 4182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size = 0; 4183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch(e->Iex.Binop.op) { 4184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Clz8Sx16: size = 0; break; 4185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Clz16Sx8: size = 1; break; 4186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Clz32Sx4: size = 2; break; 4187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: vassert(0); 4188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnary(ARMneon_CLZ, res, arg, size, True)); 4190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 4191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Cls8Sx16: 4193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Cls16Sx8: 4194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Cls32Sx4: { 4195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegV(env); 4196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg arg = iselNeonExpr(env, e->Iex.Unop.arg); 4197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size = 0; 4198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch(e->Iex.Binop.op) { 4199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Cls8Sx16: size = 0; break; 4200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Cls16Sx8: size = 1; break; 4201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Cls32Sx4: size = 2; break; 4202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: vassert(0); 4203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnary(ARMneon_CLS, res, arg, size, True)); 4205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 4206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_FtoI32Sx4_RZ: { 4208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegV(env); 4209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg arg = iselNeonExpr(env, e->Iex.Unop.arg); 4210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnary(ARMneon_VCVTFtoS, 4211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, arg, 2, True)); 4212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 4213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_FtoI32Ux4_RZ: { 4215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegV(env); 4216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg arg = iselNeonExpr(env, e->Iex.Unop.arg); 4217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnary(ARMneon_VCVTFtoU, 4218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, arg, 2, True)); 4219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 4220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_I32StoFx4: { 4222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegV(env); 4223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg arg = iselNeonExpr(env, e->Iex.Unop.arg); 4224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnary(ARMneon_VCVTStoF, 4225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, arg, 2, True)); 4226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 4227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_I32UtoFx4: { 4229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegV(env); 4230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg arg = iselNeonExpr(env, e->Iex.Unop.arg); 4231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnary(ARMneon_VCVTUtoF, 4232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, arg, 2, True)); 4233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 4234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_F16toF32x4: { 4236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegV(env); 4237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg arg = iselNeon64Expr(env, e->Iex.Unop.arg); 4238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnary(ARMneon_VCVTF16toF32, 4239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, arg, 2, True)); 4240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 4241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Recip32Fx4: { 4243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegV(env); 4244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeonExpr(env, e->Iex.Unop.arg); 4245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnary(ARMneon_VRECIPF, 4246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, 0, True)); 4247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 4248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Recip32x4: { 4250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegV(env); 4251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeonExpr(env, e->Iex.Unop.arg); 4252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnary(ARMneon_VRECIP, 4253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, 0, True)); 4254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 4255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Abs32Fx4: { 42572ca80a6a6fc069acdb73186e8e578dbf8f46af80Dmitriy Ivanov HReg res = newVRegV(env); 42582ca80a6a6fc069acdb73186e8e578dbf8f46af80Dmitriy Ivanov HReg argL = iselNeonExpr(env, e->Iex.Unop.arg); 42592ca80a6a6fc069acdb73186e8e578dbf8f46af80Dmitriy Ivanov addInstr(env, ARMInstr_NUnary(ARMneon_VABSFP, 42602ca80a6a6fc069acdb73186e8e578dbf8f46af80Dmitriy Ivanov res, argL, 0, True)); 42612ca80a6a6fc069acdb73186e8e578dbf8f46af80Dmitriy Ivanov return res; 4262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Rsqrte32Fx4: { 4264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegV(env); 4265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeonExpr(env, e->Iex.Unop.arg); 4266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnary(ARMneon_VRSQRTEFP, 4267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, 0, True)); 4268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 4269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Rsqrte32x4: { 4271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegV(env); 4272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeonExpr(env, e->Iex.Unop.arg); 4273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnary(ARMneon_VRSQRTE, 4274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, 0, True)); 4275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 4276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Neg32Fx4: { 4278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegV(env); 4279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg arg = iselNeonExpr(env, e->Iex.Unop.arg); 4280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnary(ARMneon_VNEGF, 4281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, arg, 0, True)); 4282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 4283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* ... */ 4285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: 4286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 4287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 4290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->tag == Iex_Binop) { 4291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (e->Iex.Binop.op) { 4292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_64HLtoV128: 4293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Try to match into single "VMOV reg, imm" instruction */ 4294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->Iex.Binop.arg1->tag == Iex_Const && 4295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown e->Iex.Binop.arg2->tag == Iex_Const && 4296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown typeOfIRExpr(env->type_env, e->Iex.Binop.arg1) == Ity_I64 && 4297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown typeOfIRExpr(env->type_env, e->Iex.Binop.arg2) == Ity_I64 && 4298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown e->Iex.Binop.arg1->Iex.Const.con->Ico.U64 == 4299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown e->Iex.Binop.arg2->Iex.Const.con->Ico.U64) { 4300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ULong imm64 = e->Iex.Binop.arg2->Iex.Const.con->Ico.U64; 4301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ARMNImm *imm = Imm64_to_ARMNImm(imm64); 4302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (imm) { 4303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegV(env); 4304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NeonImm(res, imm)); 4305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 4306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if ((imm64 >> 32) == 0LL && 4308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (imm = Imm64_to_ARMNImm(imm64 | (imm64 << 32))) != NULL) { 4309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg tmp1 = newVRegV(env); 4310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg tmp2 = newVRegV(env); 4311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegV(env); 4312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (imm->type < 10) { 4313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NeonImm(tmp1, ARMNImm_TI(9,0x0f))); 4314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NeonImm(tmp2, imm)); 4315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NBinary(ARMneon_VAND, 4316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, tmp1, tmp2, 4, True)); 4317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 4318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if ((imm64 & 0xFFFFFFFFLL) == 0LL && 4321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (imm = Imm64_to_ARMNImm(imm64 | (imm64 >> 32))) != NULL) { 4322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg tmp1 = newVRegV(env); 4323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg tmp2 = newVRegV(env); 4324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegV(env); 4325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (imm->type < 10) { 4326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NeonImm(tmp1, ARMNImm_TI(9,0xf0))); 4327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NeonImm(tmp2, imm)); 4328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NBinary(ARMneon_VAND, 4329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, tmp1, tmp2, 4, True)); 4330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 4331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4334b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov /* Does not match "VMOV Reg, Imm" form. We'll have to do 4335b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov it the slow way. */ 4336b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov { 4337b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov /* local scope */ 4338b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov /* Done via the stack for ease of use. */ 4339b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov /* FIXME: assumes little endian host */ 4340b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov HReg w3, w2, w1, w0; 4341b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov HReg res = newVRegV(env); 4342b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov ARMAMode1* sp_0 = ARMAMode1_RI(hregARM_R13(), 0); 4343b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov ARMAMode1* sp_4 = ARMAMode1_RI(hregARM_R13(), 4); 4344b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov ARMAMode1* sp_8 = ARMAMode1_RI(hregARM_R13(), 8); 4345b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov ARMAMode1* sp_12 = ARMAMode1_RI(hregARM_R13(), 12); 4346b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov ARMRI84* c_16 = ARMRI84_I84(16,0); 4347b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov /* Make space for SP */ 4348b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov addInstr(env, ARMInstr_Alu(ARMalu_SUB, hregARM_R13(), 4349b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov hregARM_R13(), c_16)); 4350b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 4351b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov /* Store the less significant 64 bits */ 4352b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov iselInt64Expr(&w1, &w0, env, e->Iex.Binop.arg2); 4353436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov addInstr(env, ARMInstr_LdSt32(ARMcc_AL, False/*store*/, 4354436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov w0, sp_0)); 4355436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov addInstr(env, ARMInstr_LdSt32(ARMcc_AL, False/*store*/, 4356436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov w1, sp_4)); 4357b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 4358b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov /* Store the more significant 64 bits */ 4359b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov iselInt64Expr(&w3, &w2, env, e->Iex.Binop.arg1); 4360436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov addInstr(env, ARMInstr_LdSt32(ARMcc_AL, False/*store*/, 4361436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov w2, sp_8)); 4362436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov addInstr(env, ARMInstr_LdSt32(ARMcc_AL, False/*store*/, 4363436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov w3, sp_12)); 4364b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 4365b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov /* Load result back from stack. */ 4366b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov addInstr(env, ARMInstr_NLdStQ(True/*load*/, res, 4367b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov mkARMAModeN_R(hregARM_R13()))); 4368b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 4369b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov /* Restore SP */ 4370b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov addInstr(env, ARMInstr_Alu(ARMalu_ADD, hregARM_R13(), 4371b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov hregARM_R13(), c_16)); 4372b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov return res; 4373b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } /* local scope */ 4374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown goto neon_expr_bad; 4375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_AndV128: { 4376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegV(env); 4377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeonExpr(env, e->Iex.Binop.arg1); 4378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeonExpr(env, e->Iex.Binop.arg2); 4379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NBinary(ARMneon_VAND, 4380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, argR, 4, True)); 4381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 4382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_OrV128: { 4384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegV(env); 4385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeonExpr(env, e->Iex.Binop.arg1); 4386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeonExpr(env, e->Iex.Binop.arg2); 4387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NBinary(ARMneon_VORR, 4388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, argR, 4, True)); 4389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 4390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_XorV128: { 4392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegV(env); 4393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeonExpr(env, e->Iex.Binop.arg1); 4394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeonExpr(env, e->Iex.Binop.arg2); 4395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NBinary(ARMneon_VXOR, 4396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, argR, 4, True)); 4397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 4398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Add8x16: 4400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Add16x8: 4401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Add32x4: 4402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Add64x2: { 4403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* 4404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown FIXME: remove this if not used 4405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DECLARE_PATTERN(p_vrhadd_32sx4); 4406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ULong one = (1LL << 32) | 1LL; 4407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEFINE_PATTERN(p_vrhadd_32sx4, 4408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown binop(Iop_Add32x4, 4409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown binop(Iop_Add32x4, 4410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown binop(Iop_SarN32x4, 4411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown bind(0), 4412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mkU8(1)), 4413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown binop(Iop_SarN32x4, 4414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown bind(1), 4415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mkU8(1))), 4416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown binop(Iop_SarN32x4, 4417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown binop(Iop_Add32x4, 4418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown binop(Iop_Add32x4, 4419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown binop(Iop_AndV128, 4420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown bind(0), 4421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mkU128(one)), 4422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown binop(Iop_AndV128, 4423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown bind(1), 4424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mkU128(one))), 4425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mkU128(one)), 4426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mkU8(1)))); 4427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */ 4428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegV(env); 4429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeonExpr(env, e->Iex.Binop.arg1); 4430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeonExpr(env, e->Iex.Binop.arg2); 4431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size; 4432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (e->Iex.Binop.op) { 4433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Add8x16: size = 0; break; 4434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Add16x8: size = 1; break; 4435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Add32x4: size = 2; break; 4436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Add64x2: size = 3; break; 4437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: 4438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ppIROp(e->Iex.Binop.op); 4439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vpanic("Illegal element size in VADD"); 4440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NBinary(ARMneon_VADD, 4442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, argR, size, True)); 4443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 4444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Recps32Fx4: { 4446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegV(env); 4447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeonExpr(env, e->Iex.Binop.arg1); 4448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeonExpr(env, e->Iex.Binop.arg2); 4449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size = 0; 4450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NBinary(ARMneon_VRECPS, 4451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, argR, size, True)); 4452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 4453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Rsqrts32Fx4: { 4455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegV(env); 4456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeonExpr(env, e->Iex.Binop.arg1); 4457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeonExpr(env, e->Iex.Binop.arg2); 4458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size = 0; 4459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NBinary(ARMneon_VRSQRTS, 4460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, argR, size, True)); 4461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 4462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4463436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 4464436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov // These 6 verified 18 Apr 2013 4465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_InterleaveEvenLanes8x16: 4466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_InterleaveOddLanes8x16: 4467436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case Iop_InterleaveEvenLanes16x8: 4468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_InterleaveOddLanes16x8: 4469436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case Iop_InterleaveEvenLanes32x4: 4470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_InterleaveOddLanes32x4: { 4471436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov HReg rD = newVRegV(env); 4472436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov HReg rM = newVRegV(env); 4473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeonExpr(env, e->Iex.Binop.arg1); 4474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeonExpr(env, e->Iex.Binop.arg2); 4475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size; 4476436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov Bool resRd; // is the result in rD or rM ? 4477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (e->Iex.Binop.op) { 4478436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case Iop_InterleaveOddLanes8x16: resRd = False; size = 0; break; 4479436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case Iop_InterleaveEvenLanes8x16: resRd = True; size = 0; break; 4480436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case Iop_InterleaveOddLanes16x8: resRd = False; size = 1; break; 4481436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case Iop_InterleaveEvenLanes16x8: resRd = True; size = 1; break; 4482436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case Iop_InterleaveOddLanes32x4: resRd = False; size = 2; break; 4483436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case Iop_InterleaveEvenLanes32x4: resRd = True; size = 2; break; 4484436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov default: vassert(0); 4485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4486436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov addInstr(env, ARMInstr_NUnary(ARMneon_COPY, rM, argL, 4, True)); 4487436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov addInstr(env, ARMInstr_NUnary(ARMneon_COPY, rD, argR, 4, True)); 4488436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov addInstr(env, ARMInstr_NDual(ARMneon_TRN, rD, rM, size, True)); 4489436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov return resRd ? rD : rM; 4490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4491436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 4492436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov // These 6 verified 18 Apr 2013 4493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_InterleaveHI8x16: 4494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_InterleaveLO8x16: 4495436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case Iop_InterleaveHI16x8: 4496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_InterleaveLO16x8: 4497436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case Iop_InterleaveHI32x4: 4498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_InterleaveLO32x4: { 4499436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov HReg rD = newVRegV(env); 4500436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov HReg rM = newVRegV(env); 4501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeonExpr(env, e->Iex.Binop.arg1); 4502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeonExpr(env, e->Iex.Binop.arg2); 4503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size; 4504436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov Bool resRd; // is the result in rD or rM ? 4505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (e->Iex.Binop.op) { 4506436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case Iop_InterleaveHI8x16: resRd = False; size = 0; break; 4507436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case Iop_InterleaveLO8x16: resRd = True; size = 0; break; 4508436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case Iop_InterleaveHI16x8: resRd = False; size = 1; break; 4509436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case Iop_InterleaveLO16x8: resRd = True; size = 1; break; 4510436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case Iop_InterleaveHI32x4: resRd = False; size = 2; break; 4511436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case Iop_InterleaveLO32x4: resRd = True; size = 2; break; 4512436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov default: vassert(0); 4513ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4514436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov addInstr(env, ARMInstr_NUnary(ARMneon_COPY, rM, argL, 4, True)); 4515436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov addInstr(env, ARMInstr_NUnary(ARMneon_COPY, rD, argR, 4, True)); 4516436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov addInstr(env, ARMInstr_NDual(ARMneon_ZIP, rD, rM, size, True)); 4517436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov return resRd ? rD : rM; 4518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4519436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 4520436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov // These 6 verified 18 Apr 2013 4521ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CatOddLanes8x16: 4522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CatEvenLanes8x16: 4523436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case Iop_CatOddLanes16x8: 4524ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CatEvenLanes16x8: 4525436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case Iop_CatOddLanes32x4: 4526ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CatEvenLanes32x4: { 4527436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov HReg rD = newVRegV(env); 4528436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov HReg rM = newVRegV(env); 4529ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeonExpr(env, e->Iex.Binop.arg1); 4530ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeonExpr(env, e->Iex.Binop.arg2); 4531ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size; 4532436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov Bool resRd; // is the result in rD or rM ? 4533ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (e->Iex.Binop.op) { 4534436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case Iop_CatOddLanes8x16: resRd = False; size = 0; break; 4535436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case Iop_CatEvenLanes8x16: resRd = True; size = 0; break; 4536436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case Iop_CatOddLanes16x8: resRd = False; size = 1; break; 4537436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case Iop_CatEvenLanes16x8: resRd = True; size = 1; break; 4538436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case Iop_CatOddLanes32x4: resRd = False; size = 2; break; 4539436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case Iop_CatEvenLanes32x4: resRd = True; size = 2; break; 4540436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov default: vassert(0); 4541ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4542436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov addInstr(env, ARMInstr_NUnary(ARMneon_COPY, rM, argL, 4, True)); 4543436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov addInstr(env, ARMInstr_NUnary(ARMneon_COPY, rD, argR, 4, True)); 4544436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov addInstr(env, ARMInstr_NDual(ARMneon_UZP, rD, rM, size, True)); 4545436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov return resRd ? rD : rM; 4546ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4547436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 4548ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QAdd8Ux16: 4549ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QAdd16Ux8: 4550ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QAdd32Ux4: 4551ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QAdd64Ux2: { 4552ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegV(env); 4553ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeonExpr(env, e->Iex.Binop.arg1); 4554ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeonExpr(env, e->Iex.Binop.arg2); 4555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size; 4556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (e->Iex.Binop.op) { 4557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QAdd8Ux16: size = 0; break; 4558ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QAdd16Ux8: size = 1; break; 4559ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QAdd32Ux4: size = 2; break; 4560ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QAdd64Ux2: size = 3; break; 4561ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: 4562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ppIROp(e->Iex.Binop.op); 4563ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vpanic("Illegal element size in VQADDU"); 4564ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4565ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NBinary(ARMneon_VQADDU, 4566ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, argR, size, True)); 4567ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 4568ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QAdd8Sx16: 4570ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QAdd16Sx8: 4571ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QAdd32Sx4: 4572ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QAdd64Sx2: { 4573ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegV(env); 4574ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeonExpr(env, e->Iex.Binop.arg1); 4575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeonExpr(env, e->Iex.Binop.arg2); 4576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size; 4577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (e->Iex.Binop.op) { 4578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QAdd8Sx16: size = 0; break; 4579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QAdd16Sx8: size = 1; break; 4580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QAdd32Sx4: size = 2; break; 4581ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QAdd64Sx2: size = 3; break; 4582ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: 4583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ppIROp(e->Iex.Binop.op); 4584ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vpanic("Illegal element size in VQADDS"); 4585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4586ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NBinary(ARMneon_VQADDS, 4587ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, argR, size, True)); 4588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 4589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Sub8x16: 4591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Sub16x8: 4592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Sub32x4: 4593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Sub64x2: { 4594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegV(env); 4595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeonExpr(env, e->Iex.Binop.arg1); 4596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeonExpr(env, e->Iex.Binop.arg2); 4597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size; 4598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (e->Iex.Binop.op) { 4599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Sub8x16: size = 0; break; 4600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Sub16x8: size = 1; break; 4601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Sub32x4: size = 2; break; 4602ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Sub64x2: size = 3; break; 4603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: 4604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ppIROp(e->Iex.Binop.op); 4605ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vpanic("Illegal element size in VSUB"); 4606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NBinary(ARMneon_VSUB, 4608ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, argR, size, True)); 4609ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 4610ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QSub8Ux16: 4612ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QSub16Ux8: 4613ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QSub32Ux4: 4614ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QSub64Ux2: { 4615ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegV(env); 4616ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeonExpr(env, e->Iex.Binop.arg1); 4617ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeonExpr(env, e->Iex.Binop.arg2); 4618ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size; 4619ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (e->Iex.Binop.op) { 4620ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QSub8Ux16: size = 0; break; 4621ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QSub16Ux8: size = 1; break; 4622ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QSub32Ux4: size = 2; break; 4623ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QSub64Ux2: size = 3; break; 4624ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: 4625ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ppIROp(e->Iex.Binop.op); 4626ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vpanic("Illegal element size in VQSUBU"); 4627ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4628ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NBinary(ARMneon_VQSUBU, 4629ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, argR, size, True)); 4630ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 4631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QSub8Sx16: 4633ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QSub16Sx8: 4634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QSub32Sx4: 4635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QSub64Sx2: { 4636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegV(env); 4637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeonExpr(env, e->Iex.Binop.arg1); 4638ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeonExpr(env, e->Iex.Binop.arg2); 4639ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size; 4640ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (e->Iex.Binop.op) { 4641ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QSub8Sx16: size = 0; break; 4642ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QSub16Sx8: size = 1; break; 4643ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QSub32Sx4: size = 2; break; 4644ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QSub64Sx2: size = 3; break; 4645ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: 4646ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ppIROp(e->Iex.Binop.op); 4647ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vpanic("Illegal element size in VQSUBS"); 4648ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4649ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NBinary(ARMneon_VQSUBS, 4650ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, argR, size, True)); 4651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 4652ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4653ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Max8Ux16: 4654ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Max16Ux8: 4655ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Max32Ux4: { 4656ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegV(env); 4657ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeonExpr(env, e->Iex.Binop.arg1); 4658ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeonExpr(env, e->Iex.Binop.arg2); 4659ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size; 4660ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (e->Iex.Binop.op) { 4661ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Max8Ux16: size = 0; break; 4662ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Max16Ux8: size = 1; break; 4663ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Max32Ux4: size = 2; break; 4664ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: vpanic("Illegal element size in VMAXU"); 4665ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4666ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NBinary(ARMneon_VMAXU, 4667ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, argR, size, True)); 4668ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 4669ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4670ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Max8Sx16: 4671ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Max16Sx8: 4672ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Max32Sx4: { 4673ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegV(env); 4674ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeonExpr(env, e->Iex.Binop.arg1); 4675ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeonExpr(env, e->Iex.Binop.arg2); 4676ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size; 4677ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (e->Iex.Binop.op) { 4678ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Max8Sx16: size = 0; break; 4679ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Max16Sx8: size = 1; break; 4680ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Max32Sx4: size = 2; break; 4681ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: vpanic("Illegal element size in VMAXU"); 4682ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4683ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NBinary(ARMneon_VMAXS, 4684ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, argR, size, True)); 4685ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 4686ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4687ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Min8Ux16: 4688ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Min16Ux8: 4689ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Min32Ux4: { 4690ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegV(env); 4691ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeonExpr(env, e->Iex.Binop.arg1); 4692ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeonExpr(env, e->Iex.Binop.arg2); 4693ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size; 4694ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (e->Iex.Binop.op) { 4695ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Min8Ux16: size = 0; break; 4696ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Min16Ux8: size = 1; break; 4697ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Min32Ux4: size = 2; break; 4698ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: vpanic("Illegal element size in VMAXU"); 4699ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4700ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NBinary(ARMneon_VMINU, 4701ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, argR, size, True)); 4702ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 4703ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4704ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Min8Sx16: 4705ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Min16Sx8: 4706ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Min32Sx4: { 4707ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegV(env); 4708ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeonExpr(env, e->Iex.Binop.arg1); 4709ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeonExpr(env, e->Iex.Binop.arg2); 4710ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size; 4711ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (e->Iex.Binop.op) { 4712ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Min8Sx16: size = 0; break; 4713ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Min16Sx8: size = 1; break; 4714ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Min32Sx4: size = 2; break; 4715ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: vpanic("Illegal element size in VMAXU"); 4716ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4717ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NBinary(ARMneon_VMINS, 4718ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, argR, size, True)); 4719ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 4720ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4721ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Sar8x16: 4722ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Sar16x8: 4723ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Sar32x4: 4724ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Sar64x2: { 4725ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegV(env); 4726ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeonExpr(env, e->Iex.Binop.arg1); 4727ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeonExpr(env, e->Iex.Binop.arg2); 4728ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR2 = newVRegV(env); 4729ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg zero = newVRegV(env); 4730ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size; 4731ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (e->Iex.Binop.op) { 4732ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Sar8x16: size = 0; break; 4733ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Sar16x8: size = 1; break; 4734ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Sar32x4: size = 2; break; 4735ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Sar64x2: size = 3; break; 4736ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: vassert(0); 4737ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4738ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NeonImm(zero, ARMNImm_TI(0,0))); 4739ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NBinary(ARMneon_VSUB, 4740ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown argR2, zero, argR, size, True)); 4741ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NShift(ARMneon_VSAL, 4742ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, argR2, size, True)); 4743ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 4744ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4745ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Sal8x16: 4746ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Sal16x8: 4747ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Sal32x4: 4748ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Sal64x2: { 4749ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegV(env); 4750ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeonExpr(env, e->Iex.Binop.arg1); 4751ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeonExpr(env, e->Iex.Binop.arg2); 4752ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size; 4753ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (e->Iex.Binop.op) { 4754ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Sal8x16: size = 0; break; 4755ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Sal16x8: size = 1; break; 4756ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Sal32x4: size = 2; break; 4757ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Sal64x2: size = 3; break; 4758ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: vassert(0); 4759ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4760ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NShift(ARMneon_VSAL, 4761ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, argR, size, True)); 4762ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 4763ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4764ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Shr8x16: 4765ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Shr16x8: 4766ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Shr32x4: 4767ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Shr64x2: { 4768ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegV(env); 4769ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeonExpr(env, e->Iex.Binop.arg1); 4770ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeonExpr(env, e->Iex.Binop.arg2); 4771ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR2 = newVRegV(env); 4772ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg zero = newVRegV(env); 4773ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size; 4774ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (e->Iex.Binop.op) { 4775ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Shr8x16: size = 0; break; 4776ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Shr16x8: size = 1; break; 4777ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Shr32x4: size = 2; break; 4778ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Shr64x2: size = 3; break; 4779ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: vassert(0); 4780ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4781ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NeonImm(zero, ARMNImm_TI(0,0))); 4782ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NBinary(ARMneon_VSUB, 4783ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown argR2, zero, argR, size, True)); 4784ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NShift(ARMneon_VSHL, 4785ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, argR2, size, True)); 4786ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 4787ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4788ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Shl8x16: 4789ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Shl16x8: 4790ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Shl32x4: 4791ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Shl64x2: { 4792ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegV(env); 4793ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeonExpr(env, e->Iex.Binop.arg1); 4794ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeonExpr(env, e->Iex.Binop.arg2); 4795ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size; 4796ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (e->Iex.Binop.op) { 4797ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Shl8x16: size = 0; break; 4798ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Shl16x8: size = 1; break; 4799ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Shl32x4: size = 2; break; 4800ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Shl64x2: size = 3; break; 4801ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: vassert(0); 4802ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4803ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NShift(ARMneon_VSHL, 4804ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, argR, size, True)); 4805ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 4806ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4807ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QShl8x16: 4808ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QShl16x8: 4809ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QShl32x4: 4810ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QShl64x2: { 4811ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegV(env); 4812ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeonExpr(env, e->Iex.Binop.arg1); 4813ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeonExpr(env, e->Iex.Binop.arg2); 4814ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size; 4815ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (e->Iex.Binop.op) { 4816ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QShl8x16: size = 0; break; 4817ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QShl16x8: size = 1; break; 4818ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QShl32x4: size = 2; break; 4819ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QShl64x2: size = 3; break; 4820ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: vassert(0); 4821ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4822ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NShift(ARMneon_VQSHL, 4823ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, argR, size, True)); 4824ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 4825ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4826ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QSal8x16: 4827ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QSal16x8: 4828ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QSal32x4: 4829ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QSal64x2: { 4830ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegV(env); 4831ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeonExpr(env, e->Iex.Binop.arg1); 4832ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeonExpr(env, e->Iex.Binop.arg2); 4833ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size; 4834ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (e->Iex.Binop.op) { 4835ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QSal8x16: size = 0; break; 4836ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QSal16x8: size = 1; break; 4837ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QSal32x4: size = 2; break; 4838ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QSal64x2: size = 3; break; 4839ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: vassert(0); 4840ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4841ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NShift(ARMneon_VQSAL, 4842ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, argR, size, True)); 4843ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 4844ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4845ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QShlN8x16: 4846ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QShlN16x8: 4847ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QShlN32x4: 4848ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QShlN64x2: { 4849ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegV(env); 4850ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeonExpr(env, e->Iex.Binop.arg1); 4851ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size, imm; 4852ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->Iex.Binop.arg2->tag != Iex_Const || 4853ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown typeOfIRExpr(env->type_env, e->Iex.Binop.arg2) != Ity_I8) { 4854ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vpanic("ARM taget supports Iop_QShlNAxB with constant " 4855ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "second argument only\n"); 4856ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4857ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown imm = e->Iex.Binop.arg2->Iex.Const.con->Ico.U8; 4858ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (e->Iex.Binop.op) { 4859ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QShlN8x16: size = 8 | imm; break; 4860ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QShlN16x8: size = 16 | imm; break; 4861ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QShlN32x4: size = 32 | imm; break; 4862ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QShlN64x2: size = 64 | imm; break; 4863ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: vassert(0); 4864ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4865ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnary(ARMneon_VQSHLNUU, 4866ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, size, True)); 4867ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 4868ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4869ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QShlN8Sx16: 4870ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QShlN16Sx8: 4871ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QShlN32Sx4: 4872ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QShlN64Sx2: { 4873ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegV(env); 4874ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeonExpr(env, e->Iex.Binop.arg1); 4875ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size, imm; 4876ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->Iex.Binop.arg2->tag != Iex_Const || 4877ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown typeOfIRExpr(env->type_env, e->Iex.Binop.arg2) != Ity_I8) { 4878ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vpanic("ARM taget supports Iop_QShlNASxB with constant " 4879ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "second argument only\n"); 4880ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4881ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown imm = e->Iex.Binop.arg2->Iex.Const.con->Ico.U8; 4882ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (e->Iex.Binop.op) { 4883ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QShlN8Sx16: size = 8 | imm; break; 4884ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QShlN16Sx8: size = 16 | imm; break; 4885ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QShlN32Sx4: size = 32 | imm; break; 4886ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QShlN64Sx2: size = 64 | imm; break; 4887ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: vassert(0); 4888ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4889ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnary(ARMneon_VQSHLNUS, 4890ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, size, True)); 4891ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 4892ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4893ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QSalN8x16: 4894ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QSalN16x8: 4895ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QSalN32x4: 4896ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QSalN64x2: { 4897ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegV(env); 4898ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeonExpr(env, e->Iex.Binop.arg1); 4899ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size, imm; 4900ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->Iex.Binop.arg2->tag != Iex_Const || 4901ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown typeOfIRExpr(env->type_env, e->Iex.Binop.arg2) != Ity_I8) { 4902ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vpanic("ARM taget supports Iop_QShlNAxB with constant " 4903ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "second argument only\n"); 4904ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4905ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown imm = e->Iex.Binop.arg2->Iex.Const.con->Ico.U8; 4906ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (e->Iex.Binop.op) { 4907ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QSalN8x16: size = 8 | imm; break; 4908ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QSalN16x8: size = 16 | imm; break; 4909ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QSalN32x4: size = 32 | imm; break; 4910ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QSalN64x2: size = 64 | imm; break; 4911ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: vassert(0); 4912ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4913ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnary(ARMneon_VQSHLNSS, 4914ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, size, True)); 4915ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 4916ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4917ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_ShrN8x16: 4918ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_ShrN16x8: 4919ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_ShrN32x4: 4920ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_ShrN64x2: { 4921ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegV(env); 4922ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg tmp = newVRegV(env); 4923ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeonExpr(env, e->Iex.Binop.arg1); 4924ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselIntExpr_R(env, e->Iex.Binop.arg2); 4925ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR2 = newVRegI(env); 4926ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size; 4927ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (e->Iex.Binop.op) { 4928ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_ShrN8x16: size = 0; break; 4929ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_ShrN16x8: size = 1; break; 4930ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_ShrN32x4: size = 2; break; 4931ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_ShrN64x2: size = 3; break; 4932ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: vassert(0); 4933ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4934ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_Unary(ARMun_NEG, argR2, argR)); 4935ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnary(ARMneon_DUP, 4936ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tmp, argR2, 0, True)); 4937ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NShift(ARMneon_VSHL, 4938ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, tmp, size, True)); 4939ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 4940ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4941ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_ShlN8x16: 4942ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_ShlN16x8: 4943ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_ShlN32x4: 4944ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_ShlN64x2: { 4945ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegV(env); 4946ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg tmp = newVRegV(env); 4947ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeonExpr(env, e->Iex.Binop.arg1); 4948ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselIntExpr_R(env, e->Iex.Binop.arg2); 4949ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size; 4950ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (e->Iex.Binop.op) { 4951ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_ShlN8x16: size = 0; break; 4952ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_ShlN16x8: size = 1; break; 4953ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_ShlN32x4: size = 2; break; 4954ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_ShlN64x2: size = 3; break; 4955ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: vassert(0); 4956ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4957ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnary(ARMneon_DUP, tmp, argR, 0, True)); 4958ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NShift(ARMneon_VSHL, 4959ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, tmp, size, True)); 4960ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 4961ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4962ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_SarN8x16: 4963ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_SarN16x8: 4964ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_SarN32x4: 4965ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_SarN64x2: { 4966ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegV(env); 4967ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg tmp = newVRegV(env); 4968ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeonExpr(env, e->Iex.Binop.arg1); 4969ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselIntExpr_R(env, e->Iex.Binop.arg2); 4970ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR2 = newVRegI(env); 4971ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size; 4972ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (e->Iex.Binop.op) { 4973ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_SarN8x16: size = 0; break; 4974ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_SarN16x8: size = 1; break; 4975ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_SarN32x4: size = 2; break; 4976ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_SarN64x2: size = 3; break; 4977ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: vassert(0); 4978ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4979ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_Unary(ARMun_NEG, argR2, argR)); 4980ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnary(ARMneon_DUP, tmp, argR2, 0, True)); 4981ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NShift(ARMneon_VSAL, 4982ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, tmp, size, True)); 4983ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 4984ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4985ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CmpGT8Ux16: 4986ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CmpGT16Ux8: 4987ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CmpGT32Ux4: { 4988ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegV(env); 4989ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeonExpr(env, e->Iex.Binop.arg1); 4990ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeonExpr(env, e->Iex.Binop.arg2); 4991ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size; 4992ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (e->Iex.Binop.op) { 4993ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CmpGT8Ux16: size = 0; break; 4994ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CmpGT16Ux8: size = 1; break; 4995ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CmpGT32Ux4: size = 2; break; 4996ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: vassert(0); 4997ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4998ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NBinary(ARMneon_VCGTU, 4999ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, argR, size, True)); 5000ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 5001ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5002ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CmpGT8Sx16: 5003ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CmpGT16Sx8: 5004ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CmpGT32Sx4: { 5005ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegV(env); 5006ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeonExpr(env, e->Iex.Binop.arg1); 5007ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeonExpr(env, e->Iex.Binop.arg2); 5008ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size; 5009ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (e->Iex.Binop.op) { 5010ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CmpGT8Sx16: size = 0; break; 5011ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CmpGT16Sx8: size = 1; break; 5012ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CmpGT32Sx4: size = 2; break; 5013ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: vassert(0); 5014ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5015ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NBinary(ARMneon_VCGTS, 5016ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, argR, size, True)); 5017ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 5018ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5019ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CmpEQ8x16: 5020ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CmpEQ16x8: 5021ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CmpEQ32x4: { 5022ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegV(env); 5023ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeonExpr(env, e->Iex.Binop.arg1); 5024ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeonExpr(env, e->Iex.Binop.arg2); 5025ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size; 5026ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (e->Iex.Binop.op) { 5027ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CmpEQ8x16: size = 0; break; 5028ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CmpEQ16x8: size = 1; break; 5029ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CmpEQ32x4: size = 2; break; 5030ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: vassert(0); 5031ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5032ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NBinary(ARMneon_VCEQ, 5033ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, argR, size, True)); 5034ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 5035ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5036ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Mul8x16: 5037ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Mul16x8: 5038ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Mul32x4: { 5039ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegV(env); 5040ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeonExpr(env, e->Iex.Binop.arg1); 5041ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeonExpr(env, e->Iex.Binop.arg2); 5042ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size = 0; 5043ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch(e->Iex.Binop.op) { 5044ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Mul8x16: size = 0; break; 5045ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Mul16x8: size = 1; break; 5046ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Mul32x4: size = 2; break; 5047ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: vassert(0); 5048ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5049ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NBinary(ARMneon_VMUL, 5050ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, argR, size, True)); 5051ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 5052ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5053ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Mull8Ux8: 5054ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Mull16Ux4: 5055ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Mull32Ux2: { 5056ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegV(env); 5057ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeon64Expr(env, e->Iex.Binop.arg1); 5058ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeon64Expr(env, e->Iex.Binop.arg2); 5059ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size = 0; 5060ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch(e->Iex.Binop.op) { 5061ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Mull8Ux8: size = 0; break; 5062ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Mull16Ux4: size = 1; break; 5063ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Mull32Ux2: size = 2; break; 5064ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: vassert(0); 5065ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5066ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NBinary(ARMneon_VMULLU, 5067ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, argR, size, True)); 5068ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 5069ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5070ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 5071ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Mull8Sx8: 5072ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Mull16Sx4: 5073ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Mull32Sx2: { 5074ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegV(env); 5075ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeon64Expr(env, e->Iex.Binop.arg1); 5076ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeon64Expr(env, e->Iex.Binop.arg2); 5077ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size = 0; 5078ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch(e->Iex.Binop.op) { 5079ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Mull8Sx8: size = 0; break; 5080ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Mull16Sx4: size = 1; break; 5081ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Mull32Sx2: size = 2; break; 5082ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: vassert(0); 5083ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5084ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NBinary(ARMneon_VMULLS, 5085ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, argR, size, True)); 5086ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 5087ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5088ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 5089ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QDMulHi16Sx8: 5090ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QDMulHi32Sx4: { 5091ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegV(env); 5092ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeonExpr(env, e->Iex.Binop.arg1); 5093ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeonExpr(env, e->Iex.Binop.arg2); 5094ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size = 0; 5095ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch(e->Iex.Binop.op) { 5096ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QDMulHi16Sx8: size = 1; break; 5097ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QDMulHi32Sx4: size = 2; break; 5098ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: vassert(0); 5099ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NBinary(ARMneon_VQDMULH, 5101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, argR, size, True)); 5102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 5103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 5105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QRDMulHi16Sx8: 5106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QRDMulHi32Sx4: { 5107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegV(env); 5108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeonExpr(env, e->Iex.Binop.arg1); 5109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeonExpr(env, e->Iex.Binop.arg2); 5110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size = 0; 5111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch(e->Iex.Binop.op) { 5112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QRDMulHi16Sx8: size = 1; break; 5113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QRDMulHi32Sx4: size = 2; break; 5114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: vassert(0); 5115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NBinary(ARMneon_VQRDMULH, 5117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, argR, size, True)); 5118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 5119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 5121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QDMulLong16Sx4: 5122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QDMulLong32Sx2: { 5123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegV(env); 5124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeon64Expr(env, e->Iex.Binop.arg1); 5125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeon64Expr(env, e->Iex.Binop.arg2); 5126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size = 0; 5127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch(e->Iex.Binop.op) { 5128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QDMulLong16Sx4: size = 1; break; 5129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QDMulLong32Sx2: size = 2; break; 5130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: vassert(0); 5131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NBinary(ARMneon_VQDMULL, 5133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, argR, size, True)); 5134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 5135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_PolynomialMul8x16: { 5137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegV(env); 5138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeonExpr(env, e->Iex.Binop.arg1); 5139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeonExpr(env, e->Iex.Binop.arg2); 5140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size = 0; 5141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NBinary(ARMneon_VMULP, 5142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, argR, size, True)); 5143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 5144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Max32Fx4: { 5146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegV(env); 5147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeonExpr(env, e->Iex.Binop.arg1); 5148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeonExpr(env, e->Iex.Binop.arg2); 5149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NBinary(ARMneon_VMAXF, 5150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, argR, 2, True)); 5151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 5152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Min32Fx4: { 5154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegV(env); 5155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeonExpr(env, e->Iex.Binop.arg1); 5156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeonExpr(env, e->Iex.Binop.arg2); 5157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NBinary(ARMneon_VMINF, 5158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, argR, 2, True)); 5159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 5160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_PwMax32Fx4: { 5162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegV(env); 5163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeonExpr(env, e->Iex.Binop.arg1); 5164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeonExpr(env, e->Iex.Binop.arg2); 5165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NBinary(ARMneon_VPMAXF, 5166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, argR, 2, True)); 5167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 5168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_PwMin32Fx4: { 5170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegV(env); 5171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeonExpr(env, e->Iex.Binop.arg1); 5172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeonExpr(env, e->Iex.Binop.arg2); 5173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NBinary(ARMneon_VPMINF, 5174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, argR, 2, True)); 5175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 5176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CmpGT32Fx4: { 5178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegV(env); 5179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeonExpr(env, e->Iex.Binop.arg1); 5180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeonExpr(env, e->Iex.Binop.arg2); 5181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NBinary(ARMneon_VCGTF, 5182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, argR, 2, True)); 5183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 5184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CmpGE32Fx4: { 5186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegV(env); 5187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeonExpr(env, e->Iex.Binop.arg1); 5188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeonExpr(env, e->Iex.Binop.arg2); 5189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NBinary(ARMneon_VCGEF, 5190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, argR, 2, True)); 5191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 5192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CmpEQ32Fx4: { 5194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegV(env); 5195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeonExpr(env, e->Iex.Binop.arg1); 5196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeonExpr(env, e->Iex.Binop.arg2); 5197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NBinary(ARMneon_VCEQF, 5198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, argR, 2, True)); 5199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 5200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 5202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_PolynomialMull8x8: { 5203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegV(env); 5204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeon64Expr(env, e->Iex.Binop.arg1); 5205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeon64Expr(env, e->Iex.Binop.arg2); 5206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size = 0; 5207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NBinary(ARMneon_VMULLP, 5208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, argR, size, True)); 5209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 5210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_F32ToFixed32Ux4_RZ: 5212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_F32ToFixed32Sx4_RZ: 5213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Fixed32UToF32x4_RN: 5214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Fixed32SToF32x4_RN: { 5215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegV(env); 5216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg arg = iselNeonExpr(env, e->Iex.Binop.arg1); 5217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ARMNeonUnOp op; 5218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt imm6; 5219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->Iex.Binop.arg2->tag != Iex_Const || 5220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown typeOfIRExpr(env->type_env, e->Iex.Binop.arg2) != Ity_I8) { 5221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vpanic("ARM supports FP <-> Fixed conversion with constant " 5222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "second argument less than 33 only\n"); 5223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown imm6 = e->Iex.Binop.arg2->Iex.Const.con->Ico.U8; 5225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert(imm6 <= 32 && imm6 > 0); 5226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown imm6 = 64 - imm6; 5227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch(e->Iex.Binop.op) { 5228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_F32ToFixed32Ux4_RZ: op = ARMneon_VCVTFtoFixedU; break; 5229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_F32ToFixed32Sx4_RZ: op = ARMneon_VCVTFtoFixedS; break; 5230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Fixed32UToF32x4_RN: op = ARMneon_VCVTFixedUtoF; break; 5231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Fixed32SToF32x4_RN: op = ARMneon_VCVTFixedStoF; break; 5232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: vassert(0); 5233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnary(op, res, arg, imm6, True)); 5235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 5236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* 5238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown FIXME remove if not used 5239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_VDup8x16: 5240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_VDup16x8: 5241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_VDup32x4: { 5242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegV(env); 5243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeon64Expr(env, e->Iex.Binop.arg1); 5244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt imm4; 5245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt index; 5246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->Iex.Binop.arg2->tag != Iex_Const || 5247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown typeOfIRExpr(env->type_env, e->Iex.Binop.arg2) != Ity_I8) { 5248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vpanic("ARM supports Iop_VDup with constant " 5249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "second argument less than 16 only\n"); 5250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown index = e->Iex.Binop.arg2->Iex.Const.con->Ico.U8; 5252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch(e->Iex.Binop.op) { 5253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_VDup8x16: imm4 = (index << 1) + 1; break; 5254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_VDup16x8: imm4 = (index << 2) + 2; break; 5255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_VDup32x4: imm4 = (index << 3) + 4; break; 5256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: vassert(0); 5257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (imm4 >= 16) { 5259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vpanic("ARM supports Iop_VDup with constant " 5260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "second argument less than 16 only\n"); 5261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnary(ARMneon_VDUP, 5263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, imm4, True)); 5264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 5265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */ 5267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_PwAdd8x16: 5268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_PwAdd16x8: 5269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_PwAdd32x4: { 5270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegV(env); 5271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeonExpr(env, e->Iex.Binop.arg1); 5272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeonExpr(env, e->Iex.Binop.arg2); 5273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size = 0; 5274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch(e->Iex.Binop.op) { 5275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_PwAdd8x16: size = 0; break; 5276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_PwAdd16x8: size = 1; break; 5277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_PwAdd32x4: size = 2; break; 5278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: vassert(0); 5279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NBinary(ARMneon_VPADD, 5281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, argR, size, True)); 5282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 5283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* ... */ 5285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: 5286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 5287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 5290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->tag == Iex_Triop) { 5291663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng IRTriop *triop = e->Iex.Triop.details; 5292663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 5293663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng switch (triop->op) { 5294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_ExtractV128: { 5295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegV(env); 5296663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng HReg argL = iselNeonExpr(env, triop->arg1); 5297663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng HReg argR = iselNeonExpr(env, triop->arg2); 5298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt imm4; 5299663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng if (triop->arg3->tag != Iex_Const || 5300663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng typeOfIRExpr(env->type_env, triop->arg3) != Ity_I8) { 5301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vpanic("ARM target supports Iop_ExtractV128 with constant " 5302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "third argument less than 16 only\n"); 5303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5304663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng imm4 = triop->arg3->Iex.Const.con->Ico.U8; 5305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (imm4 >= 16) { 5306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vpanic("ARM target supports Iop_ExtractV128 with constant " 5307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "third argument less than 16 only\n"); 5308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NBinary(ARMneon_VEXT, 5310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, argR, imm4, True)); 5311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 5312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 53132ca80a6a6fc069acdb73186e8e578dbf8f46af80Dmitriy Ivanov case Iop_Mul32Fx4: 53142ca80a6a6fc069acdb73186e8e578dbf8f46af80Dmitriy Ivanov case Iop_Sub32Fx4: 53152ca80a6a6fc069acdb73186e8e578dbf8f46af80Dmitriy Ivanov case Iop_Add32Fx4: { 53162ca80a6a6fc069acdb73186e8e578dbf8f46af80Dmitriy Ivanov HReg res = newVRegV(env); 53172ca80a6a6fc069acdb73186e8e578dbf8f46af80Dmitriy Ivanov HReg argL = iselNeonExpr(env, triop->arg2); 53182ca80a6a6fc069acdb73186e8e578dbf8f46af80Dmitriy Ivanov HReg argR = iselNeonExpr(env, triop->arg3); 53192ca80a6a6fc069acdb73186e8e578dbf8f46af80Dmitriy Ivanov UInt size = 0; 53202ca80a6a6fc069acdb73186e8e578dbf8f46af80Dmitriy Ivanov ARMNeonBinOp op = ARMneon_INVALID; 53212ca80a6a6fc069acdb73186e8e578dbf8f46af80Dmitriy Ivanov switch (triop->op) { 53222ca80a6a6fc069acdb73186e8e578dbf8f46af80Dmitriy Ivanov case Iop_Mul32Fx4: op = ARMneon_VMULFP; break; 53232ca80a6a6fc069acdb73186e8e578dbf8f46af80Dmitriy Ivanov case Iop_Sub32Fx4: op = ARMneon_VSUBFP; break; 53242ca80a6a6fc069acdb73186e8e578dbf8f46af80Dmitriy Ivanov case Iop_Add32Fx4: op = ARMneon_VADDFP; break; 53252ca80a6a6fc069acdb73186e8e578dbf8f46af80Dmitriy Ivanov default: vassert(0); 53262ca80a6a6fc069acdb73186e8e578dbf8f46af80Dmitriy Ivanov } 53272ca80a6a6fc069acdb73186e8e578dbf8f46af80Dmitriy Ivanov addInstr(env, ARMInstr_NBinary(op, res, argL, argR, size, True)); 53282ca80a6a6fc069acdb73186e8e578dbf8f46af80Dmitriy Ivanov return res; 53292ca80a6a6fc069acdb73186e8e578dbf8f46af80Dmitriy Ivanov } 5330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: 5331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 5332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 5335436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov if (e->tag == Iex_ITE) { // VFD 5336436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov ARMCondCode cc; 5337436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov HReg r1 = iselNeonExpr(env, e->Iex.ITE.iftrue); 5338436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov HReg r0 = iselNeonExpr(env, e->Iex.ITE.iffalse); 5339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg dst = newVRegV(env); 5340436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov addInstr(env, ARMInstr_NUnary(ARMneon_COPY, dst, r1, 4, True)); 5341436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov cc = iselCondCode(env, e->Iex.ITE.cond); 5342436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov addInstr(env, ARMInstr_NCMovQ(cc ^ 1, dst, r0)); 5343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return dst; 5344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 5346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown neon_expr_bad: 5347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ppIRExpr(e); 5348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vpanic("iselNeonExpr_wrk"); 5349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 5350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 5351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------*/ 5352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- ISEL: Floating point expressions (64 bit) ---*/ 5353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------*/ 5354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 5355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Compute a 64-bit floating point value into a register, the identity 5356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown of which is returned. As with iselIntExpr_R, the reg may be either 5357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown real or virtual; in any case it must not be changed by subsequent 5358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown code emitted by the caller. */ 5359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 5360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic HReg iselDblExpr ( ISelEnv* env, IRExpr* e ) 5361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 5362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg r = iselDblExpr_wrk( env, e ); 5363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# if 0 5364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vex_printf("\n"); ppIRExpr(e); vex_printf("\n"); 5365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 5366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert(hregClass(r) == HRcFlt64); 5367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert(hregIsVirtual(r)); 5368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return r; 5369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 5370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 5371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* DO NOT CALL THIS DIRECTLY */ 5372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic HReg iselDblExpr_wrk ( ISelEnv* env, IRExpr* e ) 5373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 5374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRType ty = typeOfIRExpr(env->type_env,e); 5375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert(e); 5376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert(ty == Ity_F64); 5377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 5378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->tag == Iex_RdTmp) { 5379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return lookupIRTemp(env, e->Iex.RdTmp.tmp); 5380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 5382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->tag == Iex_Const) { 5383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Just handle the zero case. */ 5384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRConst* con = e->Iex.Const.con; 5385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (con->tag == Ico_F64i && con->Ico.F64i == 0ULL) { 5386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg z32 = newVRegI(env); 5387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg dst = newVRegD(env); 5388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_Imm32(z32, 0)); 5389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_VXferD(True/*toD*/, dst, z32, z32)); 5390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return dst; 5391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 5394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->tag == Iex_Load && e->Iex.Load.end == Iend_LE) { 5395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ARMAModeV* am; 5396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegD(env); 5397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert(e->Iex.Load.ty == Ity_F64); 5398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown am = iselIntExpr_AModeV(env, e->Iex.Load.addr); 5399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_VLdStD(True/*isLoad*/, res, am)); 5400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 5401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 5403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->tag == Iex_Get) { 5404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // XXX This won't work if offset > 1020 or is not 0 % 4. 5405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // In which case we'll have to generate more longwinded code. 5406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ARMAModeV* am = mkARMAModeV(hregARM_R8(), e->Iex.Get.offset); 5407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegD(env); 5408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_VLdStD(True/*isLoad*/, res, am)); 5409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 5410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 5412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->tag == Iex_Unop) { 5413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (e->Iex.Unop.op) { 5414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_ReinterpI64asF64: { 5415663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng if (env->hwcaps & VEX_HWCAPS_ARM_NEON) { 5416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return iselNeon64Expr(env, e->Iex.Unop.arg); 5417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 5418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg srcHi, srcLo; 5419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg dst = newVRegD(env); 5420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown iselInt64Expr(&srcHi, &srcLo, env, e->Iex.Unop.arg); 5421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_VXferD(True/*toD*/, dst, srcHi, srcLo)); 5422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return dst; 5423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_NegF64: { 5426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg src = iselDblExpr(env, e->Iex.Unop.arg); 5427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg dst = newVRegD(env); 5428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_VUnaryD(ARMvfpu_NEG, dst, src)); 5429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return dst; 5430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_AbsF64: { 5432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg src = iselDblExpr(env, e->Iex.Unop.arg); 5433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg dst = newVRegD(env); 5434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_VUnaryD(ARMvfpu_ABS, dst, src)); 5435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return dst; 5436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_F32toF64: { 5438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg src = iselFltExpr(env, e->Iex.Unop.arg); 5439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg dst = newVRegD(env); 5440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_VCvtSD(True/*sToD*/, dst, src)); 5441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return dst; 5442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_I32UtoF64: 5444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_I32StoF64: { 5445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg src = iselIntExpr_R(env, e->Iex.Unop.arg); 5446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg f32 = newVRegF(env); 5447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg dst = newVRegD(env); 5448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bool syned = e->Iex.Unop.op == Iop_I32StoF64; 5449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* VMOV f32, src */ 5450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_VXferS(True/*toS*/, f32, src)); 5451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* FSITOD dst, f32 */ 5452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_VCvtID(True/*iToD*/, syned, 5453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown dst, f32)); 5454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return dst; 5455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: 5457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 5458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 5461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->tag == Iex_Binop) { 5462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (e->Iex.Binop.op) { 5463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_SqrtF64: { 5464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* first arg is rounding mode; we ignore it. */ 5465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg src = iselDblExpr(env, e->Iex.Binop.arg2); 5466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg dst = newVRegD(env); 5467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_VUnaryD(ARMvfpu_SQRT, dst, src)); 5468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return dst; 5469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: 5471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 5472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 5475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->tag == Iex_Triop) { 5476663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng IRTriop *triop = e->Iex.Triop.details; 5477663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 5478663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng switch (triop->op) { 5479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_DivF64: 5480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_MulF64: 5481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_AddF64: 5482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_SubF64: { 5483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ARMVfpOp op = 0; /*INVALID*/ 5484663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng HReg argL = iselDblExpr(env, triop->arg2); 5485663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng HReg argR = iselDblExpr(env, triop->arg3); 5486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg dst = newVRegD(env); 5487663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng switch (triop->op) { 5488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_DivF64: op = ARMvfp_DIV; break; 5489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_MulF64: op = ARMvfp_MUL; break; 5490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_AddF64: op = ARMvfp_ADD; break; 5491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_SubF64: op = ARMvfp_SUB; break; 5492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: vassert(0); 5493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_VAluD(op, dst, argL, argR)); 5495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return dst; 5496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: 5498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 5499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 5502436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov if (e->tag == Iex_ITE) { // VFD 5503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (ty == Ity_F64 5504436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov && typeOfIRExpr(env->type_env,e->Iex.ITE.cond) == Ity_I1) { 5505436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov HReg r1 = iselDblExpr(env, e->Iex.ITE.iftrue); 5506436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov HReg r0 = iselDblExpr(env, e->Iex.ITE.iffalse); 5507ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg dst = newVRegD(env); 5508436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov addInstr(env, ARMInstr_VUnaryD(ARMvfpu_COPY, dst, r1)); 5509436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov ARMCondCode cc = iselCondCode(env, e->Iex.ITE.cond); 5510436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov addInstr(env, ARMInstr_VCMovD(cc ^ 1, dst, r0)); 5511ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return dst; 5512ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5513ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5514ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 5515ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ppIRExpr(e); 5516ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vpanic("iselDblExpr_wrk"); 5517ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 5518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 5519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 5520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------*/ 5521ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- ISEL: Floating point expressions (32 bit) ---*/ 5522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------*/ 5523ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 5524436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov/* Compute a 32-bit floating point value into a register, the identity 5525ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown of which is returned. As with iselIntExpr_R, the reg may be either 5526ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown real or virtual; in any case it must not be changed by subsequent 5527ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown code emitted by the caller. */ 5528ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 5529ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic HReg iselFltExpr ( ISelEnv* env, IRExpr* e ) 5530ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 5531ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg r = iselFltExpr_wrk( env, e ); 5532ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# if 0 5533ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vex_printf("\n"); ppIRExpr(e); vex_printf("\n"); 5534ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 5535ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert(hregClass(r) == HRcFlt32); 5536ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert(hregIsVirtual(r)); 5537ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return r; 5538ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 5539ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 5540ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* DO NOT CALL THIS DIRECTLY */ 5541ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic HReg iselFltExpr_wrk ( ISelEnv* env, IRExpr* e ) 5542ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 5543ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRType ty = typeOfIRExpr(env->type_env,e); 5544ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert(e); 5545ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert(ty == Ity_F32); 5546ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 5547ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->tag == Iex_RdTmp) { 5548ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return lookupIRTemp(env, e->Iex.RdTmp.tmp); 5549ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5550ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 5551ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->tag == Iex_Load && e->Iex.Load.end == Iend_LE) { 5552ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ARMAModeV* am; 5553ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegF(env); 5554ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert(e->Iex.Load.ty == Ity_F32); 5555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown am = iselIntExpr_AModeV(env, e->Iex.Load.addr); 5556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_VLdStS(True/*isLoad*/, res, am)); 5557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 5558ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5559ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 5560ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->tag == Iex_Get) { 5561ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // XXX This won't work if offset > 1020 or is not 0 % 4. 5562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // In which case we'll have to generate more longwinded code. 5563ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ARMAModeV* am = mkARMAModeV(hregARM_R8(), e->Iex.Get.offset); 5564ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegF(env); 5565ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_VLdStS(True/*isLoad*/, res, am)); 5566ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 5567ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5568ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 5569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->tag == Iex_Unop) { 5570ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (e->Iex.Unop.op) { 5571ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_ReinterpI32asF32: { 5572ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg dst = newVRegF(env); 5573ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg src = iselIntExpr_R(env, e->Iex.Unop.arg); 5574ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_VXferS(True/*toS*/, dst, src)); 5575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return dst; 5576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_NegF32: { 5578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg src = iselFltExpr(env, e->Iex.Unop.arg); 5579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg dst = newVRegF(env); 5580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_VUnaryS(ARMvfpu_NEG, dst, src)); 5581ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return dst; 5582ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_AbsF32: { 5584ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg src = iselFltExpr(env, e->Iex.Unop.arg); 5585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg dst = newVRegF(env); 5586ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_VUnaryS(ARMvfpu_ABS, dst, src)); 5587ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return dst; 5588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: 5590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 5591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 5594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->tag == Iex_Binop) { 5595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (e->Iex.Binop.op) { 5596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_SqrtF32: { 5597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* first arg is rounding mode; we ignore it. */ 5598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg src = iselFltExpr(env, e->Iex.Binop.arg2); 5599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg dst = newVRegF(env); 5600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_VUnaryS(ARMvfpu_SQRT, dst, src)); 5601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return dst; 5602ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_F64toF32: { 5604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg valD = iselDblExpr(env, e->Iex.Binop.arg2); 5605ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown set_VFP_rounding_mode(env, e->Iex.Binop.arg1); 5606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg valS = newVRegF(env); 5607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* FCVTSD valS, valD */ 5608ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_VCvtSD(False/*!sToD*/, valS, valD)); 5609ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown set_VFP_rounding_default(env); 5610ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return valS; 5611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5612ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: 5613ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 5614ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5615ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5616ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 5617ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->tag == Iex_Triop) { 5618663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng IRTriop *triop = e->Iex.Triop.details; 5619663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 5620663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng switch (triop->op) { 5621ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_DivF32: 5622ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_MulF32: 5623ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_AddF32: 5624ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_SubF32: { 5625ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ARMVfpOp op = 0; /*INVALID*/ 5626663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng HReg argL = iselFltExpr(env, triop->arg2); 5627663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng HReg argR = iselFltExpr(env, triop->arg3); 5628ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg dst = newVRegF(env); 5629663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng switch (triop->op) { 5630ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_DivF32: op = ARMvfp_DIV; break; 5631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_MulF32: op = ARMvfp_MUL; break; 5632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_AddF32: op = ARMvfp_ADD; break; 5633ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_SubF32: op = ARMvfp_SUB; break; 5634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: vassert(0); 5635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_VAluS(op, dst, argL, argR)); 5637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return dst; 5638ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5639ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: 5640ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 5641ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5642ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5643ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 5644436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov if (e->tag == Iex_ITE) { // VFD 5645ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (ty == Ity_F32 5646436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov && typeOfIRExpr(env->type_env,e->Iex.ITE.cond) == Ity_I1) { 5647436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov ARMCondCode cc; 5648436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov HReg r1 = iselFltExpr(env, e->Iex.ITE.iftrue); 5649436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov HReg r0 = iselFltExpr(env, e->Iex.ITE.iffalse); 5650ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg dst = newVRegF(env); 5651436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov addInstr(env, ARMInstr_VUnaryS(ARMvfpu_COPY, dst, r1)); 5652436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov cc = iselCondCode(env, e->Iex.ITE.cond); 5653436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov addInstr(env, ARMInstr_VCMovS(cc ^ 1, dst, r0)); 5654ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return dst; 5655ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5656ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5657ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 5658ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ppIRExpr(e); 5659ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vpanic("iselFltExpr_wrk"); 5660ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 5661ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 5662ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 5663ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------*/ 5664ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- ISEL: Statements ---*/ 5665ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------*/ 5666ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 5667ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void iselStmt ( ISelEnv* env, IRStmt* stmt ) 5668ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 5669ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (vex_traceflags & VEX_TRACE_VCODE) { 5670ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vex_printf("\n-- "); 5671ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ppIRStmt(stmt); 5672ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vex_printf("\n"); 5673ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5674ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (stmt->tag) { 5675ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 5676ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* --------- STORE --------- */ 5677ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* little-endian write to memory */ 5678ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Ist_Store: { 5679ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRType tya = typeOfIRExpr(env->type_env, stmt->Ist.Store.addr); 5680ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRType tyd = typeOfIRExpr(env->type_env, stmt->Ist.Store.data); 5681ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IREndness end = stmt->Ist.Store.end; 5682ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 5683ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (tya != Ity_I32 || end != Iend_LE) 5684ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown goto stmt_fail; 5685ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 5686ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (tyd == Ity_I32) { 5687ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg rD = iselIntExpr_R(env, stmt->Ist.Store.data); 5688ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ARMAMode1* am = iselIntExpr_AMode1(env, stmt->Ist.Store.addr); 5689436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov addInstr(env, ARMInstr_LdSt32(ARMcc_AL, False/*!isLoad*/, rD, am)); 5690ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return; 5691ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5692ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (tyd == Ity_I16) { 5693ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg rD = iselIntExpr_R(env, stmt->Ist.Store.data); 5694ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ARMAMode2* am = iselIntExpr_AMode2(env, stmt->Ist.Store.addr); 5695436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov addInstr(env, ARMInstr_LdSt16(ARMcc_AL, 5696436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov False/*!isLoad*/, 5697ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown False/*!isSignedLoad*/, rD, am)); 5698ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return; 5699ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5700ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (tyd == Ity_I8) { 5701ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg rD = iselIntExpr_R(env, stmt->Ist.Store.data); 5702ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ARMAMode1* am = iselIntExpr_AMode1(env, stmt->Ist.Store.addr); 5703436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov addInstr(env, ARMInstr_LdSt8U(ARMcc_AL, False/*!isLoad*/, rD, am)); 5704ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return; 5705ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5706ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (tyd == Ity_I64) { 5707663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng if (env->hwcaps & VEX_HWCAPS_ARM_NEON) { 5708ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg dD = iselNeon64Expr(env, stmt->Ist.Store.data); 5709ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ARMAModeN* am = iselIntExpr_AModeN(env, stmt->Ist.Store.addr); 5710ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NLdStD(False, dD, am)); 5711ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 5712ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg rDhi, rDlo, rA; 5713ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown iselInt64Expr(&rDhi, &rDlo, env, stmt->Ist.Store.data); 5714ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown rA = iselIntExpr_R(env, stmt->Ist.Store.addr); 5715436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov addInstr(env, ARMInstr_LdSt32(ARMcc_AL, False/*!load*/, rDhi, 5716ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ARMAMode1_RI(rA,4))); 5717436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov addInstr(env, ARMInstr_LdSt32(ARMcc_AL, False/*!load*/, rDlo, 5718ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ARMAMode1_RI(rA,0))); 5719ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5720ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return; 5721ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5722ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (tyd == Ity_F64) { 5723ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg dD = iselDblExpr(env, stmt->Ist.Store.data); 5724ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ARMAModeV* am = iselIntExpr_AModeV(env, stmt->Ist.Store.addr); 5725ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_VLdStD(False/*!isLoad*/, dD, am)); 5726ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return; 5727ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5728ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (tyd == Ity_F32) { 5729ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg fD = iselFltExpr(env, stmt->Ist.Store.data); 5730ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ARMAModeV* am = iselIntExpr_AModeV(env, stmt->Ist.Store.addr); 5731ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_VLdStS(False/*!isLoad*/, fD, am)); 5732ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return; 5733ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5734ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (tyd == Ity_V128) { 5735ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg qD = iselNeonExpr(env, stmt->Ist.Store.data); 5736ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ARMAModeN* am = iselIntExpr_AModeN(env, stmt->Ist.Store.addr); 5737ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NLdStQ(False, qD, am)); 5738ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return; 5739ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5740ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 5741ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 5742ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5743ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 5744436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /* --------- CONDITIONAL STORE --------- */ 5745436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /* conditional little-endian write to memory */ 5746436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case Ist_StoreG: { 5747436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov IRStoreG* sg = stmt->Ist.StoreG.details; 5748436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov IRType tya = typeOfIRExpr(env->type_env, sg->addr); 5749436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov IRType tyd = typeOfIRExpr(env->type_env, sg->data); 5750436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov IREndness end = sg->end; 5751436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 5752436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov if (tya != Ity_I32 || end != Iend_LE) 5753436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov goto stmt_fail; 5754436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 5755436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov switch (tyd) { 5756436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case Ity_I8: 5757436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case Ity_I32: { 5758436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov HReg rD = iselIntExpr_R(env, sg->data); 5759436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov ARMAMode1* am = iselIntExpr_AMode1(env, sg->addr); 5760436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov ARMCondCode cc = iselCondCode(env, sg->guard); 5761436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov addInstr(env, (tyd == Ity_I32 ? ARMInstr_LdSt32 : ARMInstr_LdSt8U) 5762436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov (cc, False/*!isLoad*/, rD, am)); 5763436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov return; 5764436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } 5765436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case Ity_I16: { 5766436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov HReg rD = iselIntExpr_R(env, sg->data); 5767436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov ARMAMode2* am = iselIntExpr_AMode2(env, sg->addr); 5768436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov ARMCondCode cc = iselCondCode(env, sg->guard); 5769436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov addInstr(env, ARMInstr_LdSt16(cc, 5770436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov False/*!isLoad*/, 5771436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov False/*!isSignedLoad*/, rD, am)); 5772436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov return; 5773436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } 5774436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov default: 5775436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov break; 5776436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } 5777436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov break; 5778436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } 5779436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 5780436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /* --------- CONDITIONAL LOAD --------- */ 5781436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /* conditional little-endian load from memory */ 5782436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case Ist_LoadG: { 5783436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov IRLoadG* lg = stmt->Ist.LoadG.details; 5784436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov IRType tya = typeOfIRExpr(env->type_env, lg->addr); 5785436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov IREndness end = lg->end; 5786436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 5787436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov if (tya != Ity_I32 || end != Iend_LE) 5788436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov goto stmt_fail; 5789436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 5790436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov switch (lg->cvt) { 5791436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case ILGop_8Uto32: 5792436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case ILGop_Ident32: { 5793436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov HReg rAlt = iselIntExpr_R(env, lg->alt); 5794436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov ARMAMode1* am = iselIntExpr_AMode1(env, lg->addr); 5795436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov HReg rD = lookupIRTemp(env, lg->dst); 5796436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov addInstr(env, mk_iMOVds_RR(rD, rAlt)); 5797436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov ARMCondCode cc = iselCondCode(env, lg->guard); 5798436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov addInstr(env, (lg->cvt == ILGop_Ident32 ? ARMInstr_LdSt32 5799436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov : ARMInstr_LdSt8U) 5800436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov (cc, True/*isLoad*/, rD, am)); 5801436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov return; 5802436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } 5803436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case ILGop_16Sto32: 5804436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case ILGop_16Uto32: 5805436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case ILGop_8Sto32: { 5806436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov HReg rAlt = iselIntExpr_R(env, lg->alt); 5807436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov ARMAMode2* am = iselIntExpr_AMode2(env, lg->addr); 5808436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov HReg rD = lookupIRTemp(env, lg->dst); 5809436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov addInstr(env, mk_iMOVds_RR(rD, rAlt)); 5810436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov ARMCondCode cc = iselCondCode(env, lg->guard); 5811436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov if (lg->cvt == ILGop_8Sto32) { 5812436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov addInstr(env, ARMInstr_Ld8S(cc, rD, am)); 5813436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } else { 5814436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov vassert(lg->cvt == ILGop_16Sto32 || lg->cvt == ILGop_16Uto32); 5815436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov Bool sx = lg->cvt == ILGop_16Sto32; 5816436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov addInstr(env, ARMInstr_LdSt16(cc, True/*isLoad*/, sx, rD, am)); 5817436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } 5818436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov return; 5819436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } 5820436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov default: 5821436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov break; 5822436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } 5823436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov break; 5824436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } 5825436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 5826ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* --------- PUT --------- */ 5827ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* write guest state, fixed offset */ 5828ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Ist_Put: { 5829ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRType tyd = typeOfIRExpr(env->type_env, stmt->Ist.Put.data); 5830ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 5831ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (tyd == Ity_I32) { 5832ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg rD = iselIntExpr_R(env, stmt->Ist.Put.data); 5833ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ARMAMode1* am = ARMAMode1_RI(hregARM_R8(), stmt->Ist.Put.offset); 5834436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov addInstr(env, ARMInstr_LdSt32(ARMcc_AL, False/*!isLoad*/, rD, am)); 5835ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return; 5836ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5837ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (tyd == Ity_I64) { 5838663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng if (env->hwcaps & VEX_HWCAPS_ARM_NEON) { 5839ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg addr = newVRegI(env); 5840ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg qD = iselNeon64Expr(env, stmt->Ist.Put.data); 5841ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_Add32(addr, hregARM_R8(), 5842ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown stmt->Ist.Put.offset)); 5843ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NLdStD(False, qD, mkARMAModeN_R(addr))); 5844ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 5845ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg rDhi, rDlo; 5846ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ARMAMode1* am0 = ARMAMode1_RI(hregARM_R8(), 5847ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown stmt->Ist.Put.offset + 0); 5848ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ARMAMode1* am4 = ARMAMode1_RI(hregARM_R8(), 5849ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown stmt->Ist.Put.offset + 4); 5850ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown iselInt64Expr(&rDhi, &rDlo, env, stmt->Ist.Put.data); 5851436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov addInstr(env, ARMInstr_LdSt32(ARMcc_AL, False/*!isLoad*/, 5852436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov rDhi, am4)); 5853436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov addInstr(env, ARMInstr_LdSt32(ARMcc_AL, False/*!isLoad*/, 5854436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov rDlo, am0)); 5855ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5856ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return; 5857ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5858ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (tyd == Ity_F64) { 5859ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // XXX This won't work if offset > 1020 or is not 0 % 4. 5860ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // In which case we'll have to generate more longwinded code. 5861ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ARMAModeV* am = mkARMAModeV(hregARM_R8(), stmt->Ist.Put.offset); 5862ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg rD = iselDblExpr(env, stmt->Ist.Put.data); 5863ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_VLdStD(False/*!isLoad*/, rD, am)); 5864ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return; 5865ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5866ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (tyd == Ity_F32) { 5867ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // XXX This won't work if offset > 1020 or is not 0 % 4. 5868ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // In which case we'll have to generate more longwinded code. 5869ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ARMAModeV* am = mkARMAModeV(hregARM_R8(), stmt->Ist.Put.offset); 5870ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg rD = iselFltExpr(env, stmt->Ist.Put.data); 5871ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_VLdStS(False/*!isLoad*/, rD, am)); 5872ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return; 5873ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5874ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (tyd == Ity_V128) { 5875ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg addr = newVRegI(env); 5876ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg qD = iselNeonExpr(env, stmt->Ist.Put.data); 5877ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_Add32(addr, hregARM_R8(), 5878ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown stmt->Ist.Put.offset)); 5879ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NLdStQ(False, qD, mkARMAModeN_R(addr))); 5880ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return; 5881ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5882ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 5883ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5884ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 5885ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* --------- TMP --------- */ 5886ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* assign value to temporary */ 5887ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Ist_WrTmp: { 5888ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRTemp tmp = stmt->Ist.WrTmp.tmp; 5889ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRType ty = typeOfIRTemp(env->type_env, tmp); 5890ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 5891ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (ty == Ity_I32 || ty == Ity_I16 || ty == Ity_I8) { 5892ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ARMRI84* ri84 = iselIntExpr_RI84(NULL, False, 5893ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown env, stmt->Ist.WrTmp.data); 5894ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg dst = lookupIRTemp(env, tmp); 5895ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_Mov(dst,ri84)); 5896ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return; 5897ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5898ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (ty == Ity_I1) { 5899436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /* Here, we are generating a I1 value into a 32 bit register. 5900436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov Make sure the value in the register is only zero or one, 5901436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov but no other. This allows optimisation of the 5902436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 1Uto32(tmp:I1) case, by making it simply a copy of the 5903436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov register holding 'tmp'. The point being that the value in 5904436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov the register holding 'tmp' can only have been created 5905436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov here. */ 5906ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg dst = lookupIRTemp(env, tmp); 5907ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ARMCondCode cond = iselCondCode(env, stmt->Ist.WrTmp.data); 5908ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_Mov(dst, ARMRI84_I84(0,0))); 5909ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_CMov(cond, dst, ARMRI84_I84(1,0))); 5910ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return; 5911ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5912ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (ty == Ity_I64) { 5913663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng if (env->hwcaps & VEX_HWCAPS_ARM_NEON) { 5914ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg src = iselNeon64Expr(env, stmt->Ist.WrTmp.data); 5915ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg dst = lookupIRTemp(env, tmp); 5916ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnary(ARMneon_COPY, dst, src, 4, False)); 5917ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 5918ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg rHi, rLo, dstHi, dstLo; 5919ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown iselInt64Expr(&rHi,&rLo, env, stmt->Ist.WrTmp.data); 5920ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown lookupIRTemp64( &dstHi, &dstLo, env, tmp); 5921ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, mk_iMOVds_RR(dstHi, rHi) ); 5922ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, mk_iMOVds_RR(dstLo, rLo) ); 5923ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5924ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return; 5925ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5926ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (ty == Ity_F64) { 5927ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg src = iselDblExpr(env, stmt->Ist.WrTmp.data); 5928ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg dst = lookupIRTemp(env, tmp); 5929ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_VUnaryD(ARMvfpu_COPY, dst, src)); 5930ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return; 5931ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5932ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (ty == Ity_F32) { 5933ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg src = iselFltExpr(env, stmt->Ist.WrTmp.data); 5934ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg dst = lookupIRTemp(env, tmp); 5935ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_VUnaryS(ARMvfpu_COPY, dst, src)); 5936ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return; 5937ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5938ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (ty == Ity_V128) { 5939ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg src = iselNeonExpr(env, stmt->Ist.WrTmp.data); 5940ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg dst = lookupIRTemp(env, tmp); 5941ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnary(ARMneon_COPY, dst, src, 4, True)); 5942ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return; 5943ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5944ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 5945ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5946ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 5947ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* --------- Call to DIRTY helper --------- */ 5948ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* call complex ("dirty") helper function */ 5949ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Ist_Dirty: { 5950ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRDirty* d = stmt->Ist.Dirty.details; 5951ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 5952436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /* Figure out the return type, if any. */ 5953436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov IRType retty = Ity_INVALID; 5954436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov if (d->tmp != IRTemp_INVALID) 5955436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov retty = typeOfIRTemp(env->type_env, d->tmp); 5956436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 5957436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov Bool retty_ok = False; 5958436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov switch (retty) { 5959436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case Ity_INVALID: /* function doesn't return anything */ 5960436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case Ity_I64: case Ity_I32: case Ity_I16: case Ity_I8: 5961436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov //case Ity_V128: //ATC 5962436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov retty_ok = True; break; 5963436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov default: 5964436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov break; 5965436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } 5966436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov if (!retty_ok) 5967ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; /* will go to stmt_fail: */ 5968ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 5969436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /* Marshal args, do the call, and set the return value to 0x555..555 5970436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov if this is a conditional call that returns a value and the 5971436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov call is skipped. */ 5972436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov UInt addToSp = 0; 5973436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov RetLoc rloc = mk_RetLoc_INVALID(); 5974436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov doHelperCall( &addToSp, &rloc, env, d->guard, d->cee, retty, d->args ); 5975436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov vassert(is_sane_RetLoc(rloc)); 5976ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 5977436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /* Now figure out what to do with the returned value, if any. */ 5978436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov switch (retty) { 5979436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case Ity_INVALID: { 5980436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /* No return value. Nothing to do. */ 5981436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov vassert(d->tmp == IRTemp_INVALID); 5982436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov vassert(rloc.pri == RLPri_None); 5983436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov vassert(addToSp == 0); 5984436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov return; 5985ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5986436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case Ity_I64: { 5987436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov vassert(rloc.pri == RLPri_2Int); 5988436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov vassert(addToSp == 0); 5989436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov if (env->hwcaps & VEX_HWCAPS_ARM_NEON) { 5990436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov HReg tmp = lookupIRTemp(env, d->tmp); 5991436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov addInstr(env, ARMInstr_VXferD(True, tmp, hregARM_R1(), 5992436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov hregARM_R0())); 5993436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } else { 5994436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov HReg dstHi, dstLo; 5995436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /* The returned value is in r1:r0. Park it in the 5996436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov register-pair associated with tmp. */ 5997436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov lookupIRTemp64( &dstHi, &dstLo, env, d->tmp); 5998436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov addInstr(env, mk_iMOVds_RR(dstHi, hregARM_R1()) ); 5999436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov addInstr(env, mk_iMOVds_RR(dstLo, hregARM_R0()) ); 6000436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } 6001436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov return; 6002436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } 6003436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case Ity_I32: case Ity_I16: case Ity_I8: { 6004436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov vassert(rloc.pri == RLPri_Int); 6005436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov vassert(addToSp == 0); 6006436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /* The returned value is in r0. Park it in the register 6007436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov associated with tmp. */ 6008436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov HReg dst = lookupIRTemp(env, d->tmp); 6009436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov addInstr(env, mk_iMOVds_RR(dst, hregARM_R0()) ); 6010436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov return; 6011436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } 6012436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case Ity_V128: { 6013436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov vassert(0); // ATC. The code that this produces really 6014436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov // needs to be looked at, to verify correctness. 6015436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov // I don't think this can ever happen though, since the 6016436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov // ARM front end never produces 128-bit loads/stores. 6017436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov // Hence the following is mostly theoretical. 6018436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /* The returned value is on the stack, and *retloc tells 6019436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov us where. Fish it off the stack and then move the 6020436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov stack pointer upwards to clear it, as directed by 6021436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov doHelperCall. */ 6022436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov vassert(rloc.pri == RLPri_V128SpRel); 6023436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov vassert(rloc.spOff < 256); // else ARMRI84_I84(_,0) can't encode it 6024436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov vassert(addToSp >= 16); 6025436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov vassert(addToSp < 256); // ditto reason as for rloc.spOff 6026436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov HReg dst = lookupIRTemp(env, d->tmp); 6027436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov HReg tmp = newVRegI(env); 6028436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov HReg r13 = hregARM_R13(); // sp 6029436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov addInstr(env, ARMInstr_Alu(ARMalu_ADD, 6030436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov tmp, r13, ARMRI84_I84(rloc.spOff,0))); 6031436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov ARMAModeN* am = mkARMAModeN_R(tmp); 6032436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov addInstr(env, ARMInstr_NLdStQ(True/*load*/, dst, am)); 6033436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov addInstr(env, ARMInstr_Alu(ARMalu_ADD, 6034436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov r13, r13, ARMRI84_I84(addToSp,0))); 6035436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov return; 6036436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } 6037436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov default: 6038436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /*NOTREACHED*/ 6039436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov vassert(0); 6040ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 6041ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 6042ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 6043ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 6044ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* --------- Load Linked and Store Conditional --------- */ 6045ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Ist_LLSC: { 6046ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (stmt->Ist.LLSC.storedata == NULL) { 6047ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* LL */ 6048ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRTemp res = stmt->Ist.LLSC.result; 6049ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRType ty = typeOfIRTemp(env->type_env, res); 6050b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (ty == Ity_I32 || ty == Ity_I16 || ty == Ity_I8) { 6051ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int szB = 0; 6052ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg r_dst = lookupIRTemp(env, res); 6053ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg raddr = iselIntExpr_R(env, stmt->Ist.LLSC.addr); 6054ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (ty) { 6055ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Ity_I8: szB = 1; break; 6056b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov case Ity_I16: szB = 2; break; 6057ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Ity_I32: szB = 4; break; 6058ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: vassert(0); 6059ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 6060b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov addInstr(env, mk_iMOVds_RR(hregARM_R4(), raddr)); 6061ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_LdrEX(szB)); 6062584369aa497a47058d868ea1330f92df8bc6c7c5Kenny Root addInstr(env, mk_iMOVds_RR(r_dst, hregARM_R2())); 6063584369aa497a47058d868ea1330f92df8bc6c7c5Kenny Root return; 6064b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } 6065b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (ty == Ity_I64) { 6066584369aa497a47058d868ea1330f92df8bc6c7c5Kenny Root HReg raddr = iselIntExpr_R(env, stmt->Ist.LLSC.addr); 6067b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov addInstr(env, mk_iMOVds_RR(hregARM_R4(), raddr)); 6068b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov addInstr(env, ARMInstr_LdrEX(8)); 6069b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov /* Result is in r3:r2. On a non-NEON capable CPU, we must 6070b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov move it into a result register pair. On a NEON capable 6071b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov CPU, the result register will be a 64 bit NEON 6072b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov register, so we must move it there instead. */ 6073663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng if (env->hwcaps & VEX_HWCAPS_ARM_NEON) { 6074b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov HReg dst = lookupIRTemp(env, res); 6075b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov addInstr(env, ARMInstr_VXferD(True, dst, hregARM_R3(), 6076b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov hregARM_R2())); 60770d91818fa30df681e42e17d1f853e4db276a6a34Evgeniy Stepanov } else { 6078b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov HReg r_dst_hi, r_dst_lo; 6079b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov lookupIRTemp64(&r_dst_hi, &r_dst_lo, env, res); 6080b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov addInstr(env, mk_iMOVds_RR(r_dst_lo, hregARM_R2())); 6081b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov addInstr(env, mk_iMOVds_RR(r_dst_hi, hregARM_R3())); 60820d91818fa30df681e42e17d1f853e4db276a6a34Evgeniy Stepanov } 6083ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return; 6084ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 6085b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov /*NOTREACHED*/ 6086b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov vassert(0); 6087ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 6088ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* SC */ 6089ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRType tyd = typeOfIRExpr(env->type_env, stmt->Ist.LLSC.storedata); 6090b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (tyd == Ity_I32 || tyd == Ity_I16 || tyd == Ity_I8) { 6091b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov Int szB = 0; 6092b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov HReg rD = iselIntExpr_R(env, stmt->Ist.LLSC.storedata); 6093b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov HReg rA = iselIntExpr_R(env, stmt->Ist.LLSC.addr); 6094ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (tyd) { 6095ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Ity_I8: szB = 1; break; 6096b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov case Ity_I16: szB = 2; break; 6097ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Ity_I32: szB = 4; break; 6098ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: vassert(0); 6099ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 6100584369aa497a47058d868ea1330f92df8bc6c7c5Kenny Root addInstr(env, mk_iMOVds_RR(hregARM_R2(), rD)); 6101b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov addInstr(env, mk_iMOVds_RR(hregARM_R4(), rA)); 6102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_StrEX(szB)); 6103b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } else { 6104b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov vassert(tyd == Ity_I64); 6105b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov /* This is really ugly. There is no is/is-not NEON 6106b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov decision akin to the case for LL, because iselInt64Expr 6107b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov fudges this for us, and always gets the result into two 6108b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov GPRs even if this means moving it from a NEON 6109b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov register. */ 6110b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov HReg rDhi, rDlo; 6111b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov iselInt64Expr(&rDhi, &rDlo, env, stmt->Ist.LLSC.storedata); 6112b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov HReg rA = iselIntExpr_R(env, stmt->Ist.LLSC.addr); 6113b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov addInstr(env, mk_iMOVds_RR(hregARM_R2(), rDlo)); 6114b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov addInstr(env, mk_iMOVds_RR(hregARM_R3(), rDhi)); 6115b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov addInstr(env, mk_iMOVds_RR(hregARM_R4(), rA)); 6116b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov addInstr(env, ARMInstr_StrEX(8)); 6117b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } 6118b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov /* now r0 is 1 if failed, 0 if success. Change to IR 6119b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov conventions (0 is fail, 1 is success). Also transfer 6120b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov result to r_res. */ 6121b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov IRTemp res = stmt->Ist.LLSC.result; 6122b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov IRType ty = typeOfIRTemp(env->type_env, res); 6123b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov HReg r_res = lookupIRTemp(env, res); 6124b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov ARMRI84* one = ARMRI84_I84(1,0); 6125b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov vassert(ty == Ity_I1); 6126b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov addInstr(env, ARMInstr_Alu(ARMalu_XOR, r_res, hregARM_R0(), one)); 6127b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov /* And be conservative -- mask off all but the lowest bit */ 6128b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov addInstr(env, ARMInstr_Alu(ARMalu_AND, r_res, r_res, one)); 6129b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov return; 6130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 6131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 6132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 6133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 6134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* --------- MEM FENCE --------- */ 6135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Ist_MBE: 6136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (stmt->Ist.MBE.event) { 6137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Imbe_Fence: 6138b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov addInstr(env, ARMInstr_MFence()); 6139b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov return; 6140b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov case Imbe_CancelReservation: 6141b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov addInstr(env, ARMInstr_CLREX()); 6142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return; 6143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: 6144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 6145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 6146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 6147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 6148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* --------- INSTR MARK --------- */ 6149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Doesn't generate any executable code ... */ 6150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Ist_IMark: 6151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return; 6152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 6153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* --------- NO-OP --------- */ 6154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Ist_NoOp: 6155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return; 6156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 6157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* --------- EXIT --------- */ 6158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Ist_Exit: { 6159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (stmt->Ist.Exit.dst->tag != Ico_U32) 6160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vpanic("isel_arm: Ist_Exit: dst is not a 32-bit value"); 6161663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 6162663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng ARMCondCode cc = iselCondCode(env, stmt->Ist.Exit.guard); 6163663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng ARMAMode1* amR15T = ARMAMode1_RI(hregARM_R8(), 6164663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng stmt->Ist.Exit.offsIP); 6165663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 6166663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng /* Case: boring transfer to known address */ 6167663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng if (stmt->Ist.Exit.jk == Ijk_Boring 6168663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng || stmt->Ist.Exit.jk == Ijk_Call 6169663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng || stmt->Ist.Exit.jk == Ijk_Ret) { 6170663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng if (env->chainingAllowed) { 6171663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng /* .. almost always true .. */ 6172663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng /* Skip the event check at the dst if this is a forwards 6173663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng edge. */ 6174663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng Bool toFastEP 6175663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng = ((Addr32)stmt->Ist.Exit.dst->Ico.U32) > env->max_ga; 6176663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng if (0) vex_printf("%s", toFastEP ? "Y" : ","); 6177663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng addInstr(env, ARMInstr_XDirect(stmt->Ist.Exit.dst->Ico.U32, 6178663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng amR15T, cc, toFastEP)); 6179663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng } else { 6180663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng /* .. very occasionally .. */ 6181663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng /* We can't use chaining, so ask for an assisted transfer, 6182663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng as that's the only alternative that is allowable. */ 6183663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng HReg r = iselIntExpr_R(env, IRExpr_Const(stmt->Ist.Exit.dst)); 6184663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng addInstr(env, ARMInstr_XAssisted(r, amR15T, cc, Ijk_Boring)); 6185663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng } 6186663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng return; 6187663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng } 6188663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 6189663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng /* Case: assisted transfer to arbitrary address */ 6190663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng switch (stmt->Ist.Exit.jk) { 6191663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng /* Keep this list in sync with that in iselNext below */ 6192663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng case Ijk_ClientReq: 6193663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng case Ijk_NoDecode: 6194663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng case Ijk_NoRedir: 6195663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng case Ijk_Sys_syscall: 6196eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov case Ijk_InvalICache: 6197436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case Ijk_Yield: 6198663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng { 6199663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng HReg r = iselIntExpr_R(env, IRExpr_Const(stmt->Ist.Exit.dst)); 6200663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng addInstr(env, ARMInstr_XAssisted(r, amR15T, cc, 6201663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng stmt->Ist.Exit.jk)); 6202663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng return; 6203663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng } 6204663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng default: 6205663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng break; 6206663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng } 6207663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 6208663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng /* Do we ever expect to see any other kind? */ 6209663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng goto stmt_fail; 6210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 6211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 6212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: break; 6213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 6214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown stmt_fail: 6215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ppIRStmt(stmt); 6216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vpanic("iselStmt"); 6217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 6218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 6219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 6220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------*/ 6221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- ISEL: Basic block terminators (Nexts) ---*/ 6222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------*/ 6223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 6224663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic void iselNext ( ISelEnv* env, 6225663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng IRExpr* next, IRJumpKind jk, Int offsIP ) 6226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 6227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (vex_traceflags & VEX_TRACE_VCODE) { 6228663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng vex_printf( "\n-- PUT(%d) = ", offsIP); 6229663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng ppIRExpr( next ); 6230663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng vex_printf( "; exit-"); 6231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ppIRJumpKind(jk); 6232663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng vex_printf( "\n"); 6233663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng } 6234663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 6235663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng /* Case: boring transfer to known address */ 6236663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng if (next->tag == Iex_Const) { 6237663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng IRConst* cdst = next->Iex.Const.con; 6238663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng vassert(cdst->tag == Ico_U32); 6239663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng if (jk == Ijk_Boring || jk == Ijk_Call) { 6240663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng /* Boring transfer to known address */ 6241663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng ARMAMode1* amR15T = ARMAMode1_RI(hregARM_R8(), offsIP); 6242663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng if (env->chainingAllowed) { 6243663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng /* .. almost always true .. */ 6244663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng /* Skip the event check at the dst if this is a forwards 6245663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng edge. */ 6246663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng Bool toFastEP 6247663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng = ((Addr64)cdst->Ico.U32) > env->max_ga; 6248663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng if (0) vex_printf("%s", toFastEP ? "X" : "."); 6249663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng addInstr(env, ARMInstr_XDirect(cdst->Ico.U32, 6250663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng amR15T, ARMcc_AL, 6251663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng toFastEP)); 6252663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng } else { 6253663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng /* .. very occasionally .. */ 6254663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng /* We can't use chaining, so ask for an assisted transfer, 6255663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng as that's the only alternative that is allowable. */ 6256663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng HReg r = iselIntExpr_R(env, next); 6257663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng addInstr(env, ARMInstr_XAssisted(r, amR15T, ARMcc_AL, 6258663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng Ijk_Boring)); 6259663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng } 6260663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng return; 6261663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng } 6262663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng } 6263663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 6264663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng /* Case: call/return (==boring) transfer to any address */ 6265663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng switch (jk) { 6266663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng case Ijk_Boring: case Ijk_Ret: case Ijk_Call: { 6267663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng HReg r = iselIntExpr_R(env, next); 6268663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng ARMAMode1* amR15T = ARMAMode1_RI(hregARM_R8(), offsIP); 6269663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng if (env->chainingAllowed) { 6270663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng addInstr(env, ARMInstr_XIndir(r, amR15T, ARMcc_AL)); 6271663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng } else { 6272663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng addInstr(env, ARMInstr_XAssisted(r, amR15T, ARMcc_AL, 6273663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng Ijk_Boring)); 6274663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng } 6275663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng return; 6276663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng } 6277663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng default: 6278663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng break; 6279663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng } 6280663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 6281663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng /* Case: assisted transfer to arbitrary address */ 6282663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng switch (jk) { 6283663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng /* Keep this list in sync with that for Ist_Exit above */ 6284663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng case Ijk_ClientReq: 6285663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng case Ijk_NoDecode: 6286663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng case Ijk_NoRedir: 6287663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng case Ijk_Sys_syscall: 6288eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov case Ijk_InvalICache: 6289436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case Ijk_Yield: 6290663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng { 6291663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng HReg r = iselIntExpr_R(env, next); 6292663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng ARMAMode1* amR15T = ARMAMode1_RI(hregARM_R8(), offsIP); 6293663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng addInstr(env, ARMInstr_XAssisted(r, amR15T, ARMcc_AL, jk)); 6294663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng return; 6295663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng } 6296663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng default: 6297663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng break; 6298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 6299663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 6300663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng vex_printf( "\n-- PUT(%d) = ", offsIP); 6301663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng ppIRExpr( next ); 6302663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng vex_printf( "; exit-"); 6303663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng ppIRJumpKind(jk); 6304663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng vex_printf( "\n"); 6305663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng vassert(0); // are we expecting any other kind? 6306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 6307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 6308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 6309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------*/ 6310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Insn selector top-level ---*/ 6311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------*/ 6312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 6313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Translate an entire SB to arm code. */ 6314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 6315663860b1408516d02ebfcb3a9999a134e6cfb223Ben ChengHInstrArray* iselSB_ARM ( IRSB* bb, 6316663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng VexArch arch_host, 6317663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng VexArchInfo* archinfo_host, 6318663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng VexAbiInfo* vbi/*UNUSED*/, 6319663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng Int offs_Host_EvC_Counter, 6320663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng Int offs_Host_EvC_FailAddr, 6321663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng Bool chainingAllowed, 6322663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng Bool addProfInc, 6323663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng Addr64 max_ga ) 6324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 6325663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng Int i, j; 6326663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng HReg hreg, hregHI; 6327663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng ISelEnv* env; 6328663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng UInt hwcaps_host = archinfo_host->hwcaps; 6329663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng ARMAMode1 *amCounter, *amFailAddr; 6330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 6331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* sanity ... */ 6332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert(arch_host == VexArchARM); 6333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 6334436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /* guard against unexpected space regressions */ 6335436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov vassert(sizeof(ARMInstr) <= 28); 6336436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 6337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* hwcaps should not change from one ISEL call to another. */ 6338663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng arm_hwcaps = hwcaps_host; // JRS 2012 Mar 31: FIXME (RM) 6339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 6340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Make up an initial environment to use. */ 6341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown env = LibVEX_Alloc(sizeof(ISelEnv)); 6342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown env->vreg_ctr = 0; 6343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 6344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Set up output code array. */ 6345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown env->code = newHInstrArray(); 6346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 6347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Copy BB's type env. */ 6348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown env->type_env = bb->tyenv; 6349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 6350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Make up an IRTemp -> virtual HReg mapping. This doesn't 6351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown change as we go along. */ 6352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown env->n_vregmap = bb->tyenv->types_used; 6353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown env->vregmap = LibVEX_Alloc(env->n_vregmap * sizeof(HReg)); 6354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown env->vregmapHI = LibVEX_Alloc(env->n_vregmap * sizeof(HReg)); 6355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 6356663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng /* and finally ... */ 6357663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng env->chainingAllowed = chainingAllowed; 6358663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng env->hwcaps = hwcaps_host; 6359663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng env->max_ga = max_ga; 6360663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 6361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* For each IR temporary, allocate a suitably-kinded virtual 6362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown register. */ 6363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown j = 0; 6364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (i = 0; i < env->n_vregmap; i++) { 6365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown hregHI = hreg = INVALID_HREG; 6366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (bb->tyenv->types[i]) { 6367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Ity_I1: 6368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Ity_I8: 6369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Ity_I16: 6370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Ity_I32: hreg = mkHReg(j++, HRcInt32, True); break; 6371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Ity_I64: 6372663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng if (hwcaps_host & VEX_HWCAPS_ARM_NEON) { 6373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown hreg = mkHReg(j++, HRcFlt64, True); 6374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 6375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown hregHI = mkHReg(j++, HRcInt32, True); 6376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown hreg = mkHReg(j++, HRcInt32, True); 6377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 6378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 6379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Ity_F32: hreg = mkHReg(j++, HRcFlt32, True); break; 6380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Ity_F64: hreg = mkHReg(j++, HRcFlt64, True); break; 6381b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov case Ity_V128: hreg = mkHReg(j++, HRcVec128, True); break; 6382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: ppIRType(bb->tyenv->types[i]); 6383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vpanic("iselBB: IRTemp type"); 6384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 6385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown env->vregmap[i] = hreg; 6386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown env->vregmapHI[i] = hregHI; 6387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 6388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown env->vreg_ctr = j; 6389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 6390663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng /* The very first instruction must be an event check. */ 6391663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng amCounter = ARMAMode1_RI(hregARM_R8(), offs_Host_EvC_Counter); 6392663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng amFailAddr = ARMAMode1_RI(hregARM_R8(), offs_Host_EvC_FailAddr); 6393663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng addInstr(env, ARMInstr_EvCheck(amCounter, amFailAddr)); 6394663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 6395663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng /* Possibly a block counter increment (for profiling). At this 6396663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng point we don't know the address of the counter, so just pretend 6397663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng it is zero. It will have to be patched later, but before this 6398663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng translation is used, by a call to LibVEX_patchProfCtr. */ 6399663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng if (addProfInc) { 6400663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng addInstr(env, ARMInstr_ProfInc()); 6401663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng } 6402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 6403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Ok, finally we can iterate over the statements. */ 6404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (i = 0; i < bb->stmts_used; i++) 6405663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng iselStmt(env, bb->stmts[i]); 6406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 6407663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng iselNext(env, bb->next, bb->jumpkind, bb->offsIP); 6408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 6409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* record the number of vregs we used. */ 6410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown env->code->n_vregs = env->vreg_ctr; 6411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return env->code; 6412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 6413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 6414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 6415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------------*/ 6416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- end host_arm_isel.c ---*/ 6417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------------*/ 6418