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 10663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng Copyright (C) 2004-2012 OpenWorks LLP 11ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown info@open-works.net 12ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 13ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown NEON support is 14663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng Copyright (C) 2010-2012 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); 140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert(env->vregmapHI[tmp] != INVALID_HREG); 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{ 364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (e->tag) { 365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iex_RdTmp: case Iex_Const: case Iex_Get: 366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return False; 367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: 368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return True; 369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Do a complete function call. guard is a Ity_Bit expression 374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown indicating whether or not the call happens. If guard==NULL, the 375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown call is unconditional. Returns True iff it managed to handle this 376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown combination of arg/return types, else returns False. */ 377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic 379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownBool doHelperCall ( ISelEnv* env, 380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bool passBBP, 381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRExpr* guard, IRCallee* cee, IRExpr** args ) 382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ARMCondCode cc; 384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argregs[ARM_N_ARGREGS]; 385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg tmpregs[ARM_N_ARGREGS]; 386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bool go_fast; 387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int n_args, i, nextArgReg; 388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ULong target; 389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert(ARM_N_ARGREGS == 4); 391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Marshal args for a call and do the call. 393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown If passBBP is True, r8 (the baseblock pointer) is to be passed 395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown as the first arg. 396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown This function only deals with a tiny set of possibilities, which 398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown cover all helpers in practice. The restrictions are that only 399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown arguments in registers are supported, hence only ARM_N_REGPARMS 400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown x 32 integer bits in total can be passed. In fact the only 401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown supported arg types are I32 and I64. 402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Generating code which is both efficient and correct when 404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown parameters are to be passed in registers is difficult, for the 405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown reasons elaborated in detail in comments attached to 406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown doHelperCall() in priv/host-x86/isel.c. Here, we use a variant 407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown of the method described in those comments. 408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown The problem is split into two cases: the fast scheme and the 410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown slow scheme. In the fast scheme, arguments are computed 411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown directly into the target (real) registers. This is only safe 412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown when we can be sure that computation of each argument will not 413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown trash any real registers set by computation of any other 414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown argument. 415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown In the slow scheme, all args are first computed into vregs, and 417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown once they are all done, they are moved to the relevant real 418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown regs. This always gives correct code, but it also gives a bunch 419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown of vreg-to-rreg moves which are usually redundant but are hard 420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for the register allocator to get rid of. 421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown To decide which scheme to use, all argument expressions are 423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown first examined. If they are all so simple that it is clear they 424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown will be evaluated without use of any fixed registers, use the 425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fast scheme, else use the slow scheme. Note also that only 426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown unconditional calls may use the fast scheme, since having to 427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown compute a condition expression could itself trash real 428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown registers. 429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Note this requires being able to examine an expression and 431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown determine whether or not evaluation of it might use a fixed 432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown register. That requires knowledge of how the rest of this insn 433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown selector works. Currently just the following 3 are regarded as 434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown safe -- hopefully they cover the majority of arguments in 435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown practice: IRExpr_Tmp IRExpr_Const IRExpr_Get. 436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */ 437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Note that the cee->regparms field is meaningless on ARM hosts 439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (since there is only one calling convention) and so we always 440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ignore it. */ 441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown n_args = 0; 443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (i = 0; args[i]; i++) 444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown n_args++; 445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown argregs[0] = hregARM_R0(); 447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown argregs[1] = hregARM_R1(); 448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown argregs[2] = hregARM_R2(); 449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown argregs[3] = hregARM_R3(); 450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tmpregs[0] = tmpregs[1] = tmpregs[2] = 452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tmpregs[3] = INVALID_HREG; 453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* First decide which scheme (slow or fast) is to be used. First 455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown assume the fast scheme, and select slow if any contraindications 456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (wow) appear. */ 457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown go_fast = True; 459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (guard) { 461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (guard->tag == Iex_Const 462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && guard->Iex.Const.con->tag == Ico_U1 463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && guard->Iex.Const.con->Ico.U1 == True) { 464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* unconditional */ 465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Not manifestly unconditional -- be conservative. */ 467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown go_fast = False; 468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (go_fast) { 472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (i = 0; i < n_args; i++) { 473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (mightRequireFixedRegs(args[i])) { 474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown go_fast = False; 475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* At this point the scheme to use has been established. Generate 480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown code to get the arg values into the argument rregs. If we run 481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown out of arg regs, give up. */ 482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (go_fast) { 484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* FAST SCHEME */ 486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown nextArgReg = 0; 487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (passBBP) { 488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, mk_iMOVds_RR( argregs[nextArgReg], 489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown hregARM_R8() )); 490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown nextArgReg++; 491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (i = 0; i < n_args; i++) { 494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRType aTy = typeOfIRExpr(env->type_env, args[i]); 495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (nextArgReg >= ARM_N_ARGREGS) 496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return False; /* out of argregs */ 497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (aTy == Ity_I32) { 498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, mk_iMOVds_RR( argregs[nextArgReg], 499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown iselIntExpr_R(env, args[i]) )); 500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown nextArgReg++; 501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown else if (aTy == Ity_I64) { 503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* 64-bit args must be passed in an a reg-pair of the form 504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown n:n+1, where n is even. Hence either r0:r1 or r2:r3. 505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown On a little-endian host, the less significant word is 506ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown passed in the lower-numbered register. */ 507ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (nextArgReg & 1) { 508ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (nextArgReg >= ARM_N_ARGREGS) 509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return False; /* out of argregs */ 510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_Imm32( argregs[nextArgReg], 0xAA )); 511ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown nextArgReg++; 512ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 513ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (nextArgReg >= ARM_N_ARGREGS) 514ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return False; /* out of argregs */ 515ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg raHi, raLo; 516ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown iselInt64Expr(&raHi, &raLo, env, args[i]); 517ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, mk_iMOVds_RR( argregs[nextArgReg], raLo )); 518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown nextArgReg++; 519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, mk_iMOVds_RR( argregs[nextArgReg], raHi )); 520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown nextArgReg++; 521ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown else 523ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return False; /* unhandled arg type */ 524ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 525ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 526ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Fast scheme only applies for unconditional calls. Hence: */ 527ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown cc = ARMcc_AL; 528ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 529ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 530ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 531ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* SLOW SCHEME; move via temporaries */ 532ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown nextArgReg = 0; 533ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 534ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (passBBP) { 535ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* This is pretty stupid; better to move directly to r0 536ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown after the rest of the args are done. */ 537ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tmpregs[nextArgReg] = newVRegI(env); 538ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, mk_iMOVds_RR( tmpregs[nextArgReg], 539ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown hregARM_R8() )); 540ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown nextArgReg++; 541ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 542ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 543ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (i = 0; i < n_args; i++) { 544ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRType aTy = typeOfIRExpr(env->type_env, args[i]); 545ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (nextArgReg >= ARM_N_ARGREGS) 546ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return False; /* out of argregs */ 547ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (aTy == Ity_I32) { 548ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tmpregs[nextArgReg] = iselIntExpr_R(env, args[i]); 549ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown nextArgReg++; 550ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 551ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown else if (aTy == Ity_I64) { 552ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Same comment applies as in the Fast-scheme case. */ 553ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (nextArgReg & 1) 554ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown nextArgReg++; 555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (nextArgReg + 1 >= ARM_N_ARGREGS) 556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return False; /* out of argregs */ 557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg raHi, raLo; 558ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown iselInt64Expr(&raHi, &raLo, env, args[i]); 559ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tmpregs[nextArgReg] = raLo; 560ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown nextArgReg++; 561ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tmpregs[nextArgReg] = raHi; 562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown nextArgReg++; 563ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 564ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 565ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 566ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Now we can compute the condition. We can't do it earlier 567ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown because the argument computations could trash the condition 568ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown codes. Be a bit clever to handle the common case where the 569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown guard is 1:Bit. */ 570ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown cc = ARMcc_AL; 571ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (guard) { 572ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (guard->tag == Iex_Const 573ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && guard->Iex.Const.con->tag == Ico_U1 574ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && guard->Iex.Const.con->Ico.U1 == True) { 575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* unconditional -- do nothing */ 576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown cc = iselCondCode( env, guard ); 578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 581ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Move the args to their final destinations. */ 582ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (i = 0; i < nextArgReg; i++) { 583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (tmpregs[i] == INVALID_HREG) { // Skip invalid regs 584ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_Imm32( argregs[i], 0xAA )); 585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown continue; 586ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 587ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* None of these insns, including any spill code that might 588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown be generated, may alter the condition codes. */ 589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr( env, mk_iMOVds_RR( argregs[i], tmpregs[i] ) ); 590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Should be assured by checks above */ 595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert(nextArgReg <= ARM_N_ARGREGS); 596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown target = (HWord)Ptr_to_ULong(cee->addr); 598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* nextArgReg doles out argument registers. Since these are 600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown assigned in the order r0, r1, r2, r3, its numeric value at this 601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown point, which must be between 0 and 4 inclusive, is going to be 602ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown equal to the number of arg regs in use for the call. Hence bake 603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown that number into the call (we'll need to know it when doing 604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown register allocation, to know what regs the call reads.) 605ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown There is a bit of a twist -- harmless but worth recording. 607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Suppose the arg types are (Ity_I32, Ity_I64). Then we will have 608ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown the first arg in r0 and the second in r3:r2, but r1 isn't used. 609ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown We nevertheless have nextArgReg==4 and bake that into the call 610ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown instruction. This will mean the register allocator wil believe 611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown this insn reads r1 when in fact it doesn't. But that's 612ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown harmless; it just artificially extends the live range of r1 613ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown unnecessarily. The best fix would be to put into the 614ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown instruction, a bitmask indicating which of r0/1/2/3 carry live 615ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown values. But that's too much hassle. */ 616ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 617ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Finally, the call itself. */ 618ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_Call( cc, target, nextArgReg )); 619ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 620ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return True; /* success */ 621ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 622ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 623ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 624ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------*/ 625ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- ISEL: Integer expressions (32/16/8 bit) ---*/ 626ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------*/ 627ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 628ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Select insns for an integer-typed expression, and add them to the 629ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown code list. Return a reg holding the result. This reg will be a 630ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown virtual register. THE RETURNED REG MUST NOT BE MODIFIED. If you 631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown want to modify it, ask for a new vreg, copy it in there, and modify 632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown the copy. The register allocator will do its best to map both 633ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vregs to the same real register, so the copies will often disappear 634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown later in the game. 635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown This should handle expressions of 32, 16 and 8-bit type. All 637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown results are returned in a 32-bit register. For 16- and 8-bit 638ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown expressions, the upper 16/24 bits are arbitrary, so you should mask 639ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown or sign extend partial values if necessary. 640ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/ 641ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 642ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* --------------------- AMode1 --------------------- */ 643ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 644ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Return an AMode1 which computes the value of the specified 645ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown expression, possibly also adding insns to the code list as a 646ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown result. The expression may only be a 32-bit one. 647ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/ 648ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 649ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool sane_AMode1 ( ARMAMode1* am ) 650ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (am->tag) { 652ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case ARMam1_RI: 653ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return 654ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown toBool( hregClass(am->ARMam1.RI.reg) == HRcInt32 655ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && (hregIsVirtual(am->ARMam1.RI.reg) 656ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown || am->ARMam1.RI.reg == hregARM_R8()) 657ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && am->ARMam1.RI.simm13 >= -4095 658ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && am->ARMam1.RI.simm13 <= 4095 ); 659ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case ARMam1_RRS: 660ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return 661ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown toBool( hregClass(am->ARMam1.RRS.base) == HRcInt32 662ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && hregIsVirtual(am->ARMam1.RRS.base) 663ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && hregClass(am->ARMam1.RRS.index) == HRcInt32 664ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && hregIsVirtual(am->ARMam1.RRS.index) 665ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && am->ARMam1.RRS.shift >= 0 666ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && am->ARMam1.RRS.shift <= 3 ); 667ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: 668ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vpanic("sane_AMode: unknown ARM AMode1 tag"); 669ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 670ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 671ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 672ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic ARMAMode1* iselIntExpr_AMode1 ( ISelEnv* env, IRExpr* e ) 673ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 674ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ARMAMode1* am = iselIntExpr_AMode1_wrk(env, e); 675ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert(sane_AMode1(am)); 676ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return am; 677ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 678ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 679ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic ARMAMode1* iselIntExpr_AMode1_wrk ( ISelEnv* env, IRExpr* e ) 680ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 681ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRType ty = typeOfIRExpr(env->type_env,e); 682ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert(ty == Ity_I32); 683ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 684ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* FIXME: add RRS matching */ 685ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 686ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* {Add32,Sub32}(expr,simm13) */ 687ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->tag == Iex_Binop 688ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && (e->Iex.Binop.op == Iop_Add32 || e->Iex.Binop.op == Iop_Sub32) 689ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && e->Iex.Binop.arg2->tag == Iex_Const 690ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && e->Iex.Binop.arg2->Iex.Const.con->tag == Ico_U32) { 691ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int simm = (Int)e->Iex.Binop.arg2->Iex.Const.con->Ico.U32; 692ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (simm >= -4095 && simm <= 4095) { 693ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg reg; 694ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->Iex.Binop.op == Iop_Sub32) 695ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown simm = -simm; 696ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown reg = iselIntExpr_R(env, e->Iex.Binop.arg1); 697ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return ARMAMode1_RI(reg, simm); 698ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 699ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 700ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 701ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Doesn't match anything in particular. Generate it into 702ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown a register and use that. */ 703ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown { 704ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg reg = iselIntExpr_R(env, e); 705ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return ARMAMode1_RI(reg, 0); 706ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 707ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 708ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 709ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 710ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 711ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* --------------------- AMode2 --------------------- */ 712ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 713ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Return an AMode2 which computes the value of the specified 714ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown expression, possibly also adding insns to the code list as a 715ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown result. The expression may only be a 32-bit one. 716ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/ 717ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 718ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool sane_AMode2 ( ARMAMode2* am ) 719ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 720ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (am->tag) { 721ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case ARMam2_RI: 722ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return 723ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown toBool( hregClass(am->ARMam2.RI.reg) == HRcInt32 724ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && hregIsVirtual(am->ARMam2.RI.reg) 725ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && am->ARMam2.RI.simm9 >= -255 726ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && am->ARMam2.RI.simm9 <= 255 ); 727ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case ARMam2_RR: 728ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return 729ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown toBool( hregClass(am->ARMam2.RR.base) == HRcInt32 730ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && hregIsVirtual(am->ARMam2.RR.base) 731ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && hregClass(am->ARMam2.RR.index) == HRcInt32 732ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && hregIsVirtual(am->ARMam2.RR.index) ); 733ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: 734ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vpanic("sane_AMode: unknown ARM AMode2 tag"); 735ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 736ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 737ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 738ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic ARMAMode2* iselIntExpr_AMode2 ( ISelEnv* env, IRExpr* e ) 739ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 740ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ARMAMode2* am = iselIntExpr_AMode2_wrk(env, e); 741ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert(sane_AMode2(am)); 742ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return am; 743ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 744ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 745ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic ARMAMode2* iselIntExpr_AMode2_wrk ( ISelEnv* env, IRExpr* e ) 746ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 747ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRType ty = typeOfIRExpr(env->type_env,e); 748ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert(ty == Ity_I32); 749ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 750ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* FIXME: add RR matching */ 751ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 752ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* {Add32,Sub32}(expr,simm8) */ 753ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->tag == Iex_Binop 754ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && (e->Iex.Binop.op == Iop_Add32 || e->Iex.Binop.op == Iop_Sub32) 755ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && e->Iex.Binop.arg2->tag == Iex_Const 756ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && e->Iex.Binop.arg2->Iex.Const.con->tag == Ico_U32) { 757ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int simm = (Int)e->Iex.Binop.arg2->Iex.Const.con->Ico.U32; 758ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (simm >= -255 && simm <= 255) { 759ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg reg; 760ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->Iex.Binop.op == Iop_Sub32) 761ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown simm = -simm; 762ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown reg = iselIntExpr_R(env, e->Iex.Binop.arg1); 763ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return ARMAMode2_RI(reg, simm); 764ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 765ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 766ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 767ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Doesn't match anything in particular. Generate it into 768ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown a register and use that. */ 769ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown { 770ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg reg = iselIntExpr_R(env, e); 771ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return ARMAMode2_RI(reg, 0); 772ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 773ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 774ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 775ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 776ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 777ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* --------------------- AModeV --------------------- */ 778ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 779ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Return an AModeV which computes the value of the specified 780ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown expression, possibly also adding insns to the code list as a 781ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown result. The expression may only be a 32-bit one. 782ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/ 783ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 784ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool sane_AModeV ( ARMAModeV* am ) 785ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 786ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return toBool( hregClass(am->reg) == HRcInt32 787ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && hregIsVirtual(am->reg) 788ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && am->simm11 >= -1020 && am->simm11 <= 1020 789ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && 0 == (am->simm11 & 3) ); 790ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 791ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 792ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic ARMAModeV* iselIntExpr_AModeV ( ISelEnv* env, IRExpr* e ) 793ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 794ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ARMAModeV* am = iselIntExpr_AModeV_wrk(env, e); 795ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert(sane_AModeV(am)); 796ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return am; 797ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 798ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 799ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic ARMAModeV* iselIntExpr_AModeV_wrk ( ISelEnv* env, IRExpr* e ) 800ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 801ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRType ty = typeOfIRExpr(env->type_env,e); 802ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert(ty == Ity_I32); 803ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 804ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* {Add32,Sub32}(expr, simm8 << 2) */ 805ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->tag == Iex_Binop 806ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && (e->Iex.Binop.op == Iop_Add32 || e->Iex.Binop.op == Iop_Sub32) 807ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && e->Iex.Binop.arg2->tag == Iex_Const 808ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && e->Iex.Binop.arg2->Iex.Const.con->tag == Ico_U32) { 809ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int simm = (Int)e->Iex.Binop.arg2->Iex.Const.con->Ico.U32; 810ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (simm >= -1020 && simm <= 1020 && 0 == (simm & 3)) { 811ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg reg; 812ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->Iex.Binop.op == Iop_Sub32) 813ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown simm = -simm; 814ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown reg = iselIntExpr_R(env, e->Iex.Binop.arg1); 815ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return mkARMAModeV(reg, simm); 816ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 817ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 818ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 819ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Doesn't match anything in particular. Generate it into 820ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown a register and use that. */ 821ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown { 822ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg reg = iselIntExpr_R(env, e); 823ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return mkARMAModeV(reg, 0); 824ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 825ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 826ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 827ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 828ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* -------------------- AModeN -------------------- */ 829ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 830ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic ARMAModeN* iselIntExpr_AModeN ( ISelEnv* env, IRExpr* e ) 831ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 832ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return iselIntExpr_AModeN_wrk(env, e); 833ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 834ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 835ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic ARMAModeN* iselIntExpr_AModeN_wrk ( ISelEnv* env, IRExpr* e ) 836ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 837ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg reg = iselIntExpr_R(env, e); 838ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return mkARMAModeN_R(reg); 839ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 840ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 841ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 842ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* --------------------- RI84 --------------------- */ 843ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 844ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Select instructions to generate 'e' into a RI84. If mayInv is 845ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown true, then the caller will also accept an I84 form that denotes 846ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 'not e'. In this case didInv may not be NULL, and *didInv is set 847ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown to True. This complication is so as to allow generation of an RI84 848ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown which is suitable for use in either an AND or BIC instruction, 849ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown without knowing (before this call) which one. 850ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/ 851ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic ARMRI84* iselIntExpr_RI84 ( /*OUT*/Bool* didInv, Bool mayInv, 852ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ISelEnv* env, IRExpr* e ) 853ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 854ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ARMRI84* ri; 855ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (mayInv) 856ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert(didInv != NULL); 857ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ri = iselIntExpr_RI84_wrk(didInv, mayInv, env, e); 858ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* sanity checks ... */ 859ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (ri->tag) { 860ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case ARMri84_I84: 861ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return ri; 862ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case ARMri84_R: 863ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert(hregClass(ri->ARMri84.R.reg) == HRcInt32); 864ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert(hregIsVirtual(ri->ARMri84.R.reg)); 865ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return ri; 866ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: 867ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vpanic("iselIntExpr_RI84: unknown arm RI84 tag"); 868ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 869ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 870ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 871ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* DO NOT CALL THIS DIRECTLY ! */ 872ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic ARMRI84* iselIntExpr_RI84_wrk ( /*OUT*/Bool* didInv, Bool mayInv, 873ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ISelEnv* env, IRExpr* e ) 874ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 875ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRType ty = typeOfIRExpr(env->type_env,e); 876ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert(ty == Ity_I32 || ty == Ity_I16 || ty == Ity_I8); 877ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 878ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (didInv) *didInv = False; 879ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 880ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* special case: immediate */ 881ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->tag == Iex_Const) { 882ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt u, u8 = 0x100, u4 = 0x10; /* both invalid */ 883ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (e->Iex.Const.con->tag) { 884ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Ico_U32: u = e->Iex.Const.con->Ico.U32; break; 885ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Ico_U16: u = 0xFFFF & (e->Iex.Const.con->Ico.U16); break; 886ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Ico_U8: u = 0xFF & (e->Iex.Const.con->Ico.U8); break; 887ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: vpanic("iselIntExpr_RI84.Iex_Const(armh)"); 888ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 889ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (fitsIn8x4(&u8, &u4, u)) { 890ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return ARMRI84_I84( (UShort)u8, (UShort)u4 ); 891ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 892ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (mayInv && fitsIn8x4(&u8, &u4, ~u)) { 893ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert(didInv); 894ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *didInv = True; 895ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return ARMRI84_I84( (UShort)u8, (UShort)u4 ); 896ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 897ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* else fail, fall through to default case */ 898ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 899ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 900ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* default case: calculate into a register and return that */ 901ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown { 902ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg r = iselIntExpr_R ( env, e ); 903ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return ARMRI84_R(r); 904ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 905ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 906ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 907ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 908ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* --------------------- RI5 --------------------- */ 909ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 910ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Select instructions to generate 'e' into a RI5. */ 911ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 912ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic ARMRI5* iselIntExpr_RI5 ( ISelEnv* env, IRExpr* e ) 913ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 914ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ARMRI5* ri = iselIntExpr_RI5_wrk(env, e); 915ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* sanity checks ... */ 916ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (ri->tag) { 917ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case ARMri5_I5: 918ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return ri; 919ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case ARMri5_R: 920ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert(hregClass(ri->ARMri5.R.reg) == HRcInt32); 921ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert(hregIsVirtual(ri->ARMri5.R.reg)); 922ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return ri; 923ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: 924ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vpanic("iselIntExpr_RI5: unknown arm RI5 tag"); 925ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 926ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 927ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 928ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* DO NOT CALL THIS DIRECTLY ! */ 929ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic ARMRI5* iselIntExpr_RI5_wrk ( ISelEnv* env, IRExpr* e ) 930ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 931ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRType ty = typeOfIRExpr(env->type_env,e); 932ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert(ty == Ity_I32 || ty == Ity_I8); 933ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 934ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* special case: immediate */ 935ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->tag == Iex_Const) { 936ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt u; /* both invalid */ 937ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (e->Iex.Const.con->tag) { 938ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Ico_U32: u = e->Iex.Const.con->Ico.U32; break; 939ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Ico_U16: u = 0xFFFF & (e->Iex.Const.con->Ico.U16); break; 940ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Ico_U8: u = 0xFF & (e->Iex.Const.con->Ico.U8); break; 941ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: vpanic("iselIntExpr_RI5.Iex_Const(armh)"); 942ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 943ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (u >= 1 && u <= 31) { 944ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return ARMRI5_I5(u); 945ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 946ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* else fail, fall through to default case */ 947ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 948ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 949ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* default case: calculate into a register and return that */ 950ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown { 951ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg r = iselIntExpr_R ( env, e ); 952ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return ARMRI5_R(r); 953ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 954ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 955ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 956ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 957ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* ------------------- CondCode ------------------- */ 958ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 959ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Generate code to evaluated a bit-typed expression, returning the 960ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown condition code which would correspond when the expression would 961ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown notionally have returned 1. */ 962ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 963ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic ARMCondCode iselCondCode ( ISelEnv* env, IRExpr* e ) 964ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 965ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ARMCondCode cc = iselCondCode_wrk(env,e); 966ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert(cc != ARMcc_NV); 967ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return cc; 968ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 969ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 970ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic ARMCondCode iselCondCode_wrk ( ISelEnv* env, IRExpr* e ) 971ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 972ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert(e); 973ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert(typeOfIRExpr(env->type_env,e) == Ity_I1); 974ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 975ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* var */ 976ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->tag == Iex_RdTmp) { 977ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg rTmp = lookupIRTemp(env, e->Iex.RdTmp.tmp); 978ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* CmpOrTst doesn't modify rTmp; so this is OK. */ 979ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ARMRI84* one = ARMRI84_I84(1,0); 980ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_CmpOrTst(False/*test*/, rTmp, one)); 981ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return ARMcc_NE; 982ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 983ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 984ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Not1(e) */ 985ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->tag == Iex_Unop && e->Iex.Unop.op == Iop_Not1) { 986ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Generate code for the arg, and negate the test condition */ 987ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return 1 ^ iselCondCode(env, e->Iex.Unop.arg); 988ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 989ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 990ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* --- patterns rooted at: 32to1 --- */ 991ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 992ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->tag == Iex_Unop 993ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && e->Iex.Unop.op == Iop_32to1) { 994ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg rTmp = iselIntExpr_R(env, e->Iex.Unop.arg); 995ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ARMRI84* one = ARMRI84_I84(1,0); 996ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_CmpOrTst(False/*test*/, rTmp, one)); 997ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return ARMcc_NE; 998ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 999ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1000ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* --- patterns rooted at: CmpNEZ8 --- */ 1001ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1002ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->tag == Iex_Unop 1003ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && e->Iex.Unop.op == Iop_CmpNEZ8) { 1004ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg r1 = iselIntExpr_R(env, e->Iex.Unop.arg); 1005ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ARMRI84* xFF = ARMRI84_I84(0xFF,0); 1006ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_CmpOrTst(False/*!isCmp*/, r1, xFF)); 1007ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return ARMcc_NE; 1008ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1009ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1010ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* --- patterns rooted at: CmpNEZ32 --- */ 1011ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1012ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->tag == Iex_Unop 1013ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && e->Iex.Unop.op == Iop_CmpNEZ32) { 1014ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg r1 = iselIntExpr_R(env, e->Iex.Unop.arg); 1015ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ARMRI84* zero = ARMRI84_I84(0,0); 1016ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_CmpOrTst(True/*isCmp*/, r1, zero)); 1017ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return ARMcc_NE; 1018ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1019ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1020ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* --- patterns rooted at: CmpNEZ64 --- */ 1021ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1022ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->tag == Iex_Unop 1023ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && e->Iex.Unop.op == Iop_CmpNEZ64) { 1024ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg tHi, tLo; 1025ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg tmp = newVRegI(env); 1026ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ARMRI84* zero = ARMRI84_I84(0,0); 1027ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown iselInt64Expr(&tHi, &tLo, env, e->Iex.Unop.arg); 1028ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_Alu(ARMalu_OR, tmp, tHi, ARMRI84_R(tLo))); 1029ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_CmpOrTst(True/*isCmp*/, tmp, zero)); 1030ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return ARMcc_NE; 1031ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1032ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1033ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* --- Cmp*32*(x,y) --- */ 1034ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->tag == Iex_Binop 1035ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && (e->Iex.Binop.op == Iop_CmpEQ32 1036ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown || e->Iex.Binop.op == Iop_CmpNE32 1037ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown || e->Iex.Binop.op == Iop_CmpLT32S 1038ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown || e->Iex.Binop.op == Iop_CmpLT32U 1039ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown || e->Iex.Binop.op == Iop_CmpLE32S 1040ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown || e->Iex.Binop.op == Iop_CmpLE32U)) { 1041ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselIntExpr_R(env, e->Iex.Binop.arg1); 1042ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ARMRI84* argR = iselIntExpr_RI84(NULL,False, 1043ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown env, e->Iex.Binop.arg2); 1044ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_CmpOrTst(True/*isCmp*/, argL, argR)); 1045ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (e->Iex.Binop.op) { 1046ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CmpEQ32: return ARMcc_EQ; 1047ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CmpNE32: return ARMcc_NE; 1048ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CmpLT32S: return ARMcc_LT; 1049ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CmpLT32U: return ARMcc_LO; 1050ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CmpLE32S: return ARMcc_LE; 1051ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CmpLE32U: return ARMcc_LS; 1052ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: vpanic("iselCondCode(arm): CmpXX32"); 1053ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1054ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1055ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1056ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* --- CasCmpEQ* --- */ 1057ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Ist_Cas has a dummy argument to compare with, so comparison is 1058ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown always true. */ 1059ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->tag == Iex_Binop 1060ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && (e->Iex.Binop.op == Iop_CasCmpEQ32 1061ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown || e->Iex.Binop.op == Iop_CasCmpEQ16 1062ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown || e->Iex.Binop.op == Iop_CasCmpEQ8)) { 1063ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return ARMcc_AL; 1064ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1065ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1066ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ppIRExpr(e); 1067ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vpanic("iselCondCode"); 1068ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1069ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1070ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1071ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* --------------------- Reg --------------------- */ 1072ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1073ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic HReg iselIntExpr_R ( ISelEnv* env, IRExpr* e ) 1074ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1075ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg r = iselIntExpr_R_wrk(env, e); 1076ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* sanity checks ... */ 1077ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# if 0 1078ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vex_printf("\n"); ppIRExpr(e); vex_printf("\n"); 1079ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 1080ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert(hregClass(r) == HRcInt32); 1081ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert(hregIsVirtual(r)); 1082ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return r; 1083ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1084ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1085ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* DO NOT CALL THIS DIRECTLY ! */ 1086ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic HReg iselIntExpr_R_wrk ( ISelEnv* env, IRExpr* e ) 1087ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1088ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRType ty = typeOfIRExpr(env->type_env,e); 1089ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert(ty == Ity_I32 || ty == Ity_I16 || ty == Ity_I8); 1090ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// vassert(ty == Ity_I64 || ty == Ity_I32 || ty == Ity_I16 || ty == Ity_I8); 1091ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1092ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (e->tag) { 1093ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1094ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* --------- TEMP --------- */ 1095ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iex_RdTmp: { 1096ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return lookupIRTemp(env, e->Iex.RdTmp.tmp); 1097ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1098ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1099ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* --------- LOAD --------- */ 1100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iex_Load: { 1101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg dst = newVRegI(env); 1102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->Iex.Load.end != Iend_LE) 1104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown goto irreducible; 1105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (ty == Ity_I32) { 1107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ARMAMode1* amode = iselIntExpr_AMode1 ( env, e->Iex.Load.addr ); 1108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_LdSt32(True/*isLoad*/, dst, amode)); 1109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return dst; 1110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (ty == Ity_I16) { 1112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ARMAMode2* amode = iselIntExpr_AMode2 ( env, e->Iex.Load.addr ); 1113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_LdSt16(True/*isLoad*/, False/*!signedLoad*/, 1114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown dst, amode)); 1115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return dst; 1116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (ty == Ity_I8) { 1118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ARMAMode1* amode = iselIntExpr_AMode1 ( env, e->Iex.Load.addr ); 1119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_LdSt8U(True/*isLoad*/, dst, amode)); 1120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return dst; 1121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz if (ty == Ity_I16) { 1124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz addInstr(env, X86Instr_LoadEX(2,False,amode,dst)); 1125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz return dst; 1126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz } 1127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz if (ty == Ity_I8) { 1128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz addInstr(env, X86Instr_LoadEX(1,False,amode,dst)); 1129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz return dst; 1130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz } 1131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 1132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz /* --------- TERNARY OP --------- */ 1135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz case Iex_Triop: { 1136663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng//zz IRTriop *triop = e->Iex.Triop.details; 1137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz /* C3210 flags following FPU partial remainder (fprem), both 1138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz IEEE compliant (PREM1) and non-IEEE compliant (PREM). */ 1139663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng//zz if (triop->op == Iop_PRemC3210F64 1140663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng//zz || triop->op == Iop_PRem1C3210F64) { 1141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz HReg junk = newVRegF(env); 1142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz HReg dst = newVRegI(env); 1143663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng//zz HReg srcL = iselDblExpr(env, triop->arg2); 1144663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng//zz HReg srcR = iselDblExpr(env, triop->arg3); 1145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz /* XXXROUNDINGFIXME */ 1146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz /* set roundingmode here */ 1147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz addInstr(env, X86Instr_FpBinary( 1148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz e->Iex.Binop.op==Iop_PRemC3210F64 1149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz ? Xfp_PREM : Xfp_PREM1, 1150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz srcL,srcR,junk 1151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz )); 1152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz /* The previous pseudo-insn will have left the FPU's C3210 1153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz flags set correctly. So bag them. */ 1154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz addInstr(env, X86Instr_FpStSW_AX()); 1155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz addInstr(env, mk_iMOVsd_RR(hregX86_EAX(), dst)); 1156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz addInstr(env, X86Instr_Alu32R(Xalu_AND, X86RMI_Imm(0x4700), dst)); 1157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz return dst; 1158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz } 1159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz 1160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz break; 1161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz } 1162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* --------- BINARY OP --------- */ 1164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iex_Binop: { 1165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ARMAluOp aop = 0; /* invalid */ 1167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ARMShiftOp sop = 0; /* invalid */ 1168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* ADD/SUB/AND/OR/XOR */ 1170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (e->Iex.Binop.op) { 1171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_And32: { 1172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bool didInv = False; 1173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg dst = newVRegI(env); 1174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselIntExpr_R(env, e->Iex.Binop.arg1); 1175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ARMRI84* argR = iselIntExpr_RI84(&didInv, True/*mayInv*/, 1176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown env, e->Iex.Binop.arg2); 1177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_Alu(didInv ? ARMalu_BIC : ARMalu_AND, 1178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown dst, argL, argR)); 1179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return dst; 1180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Or32: aop = ARMalu_OR; goto std_binop; 1182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Xor32: aop = ARMalu_XOR; goto std_binop; 1183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Sub32: aop = ARMalu_SUB; goto std_binop; 1184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Add32: aop = ARMalu_ADD; goto std_binop; 1185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown std_binop: { 1186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg dst = newVRegI(env); 1187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselIntExpr_R(env, e->Iex.Binop.arg1); 1188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ARMRI84* argR = iselIntExpr_RI84(NULL, False/*mayInv*/, 1189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown env, e->Iex.Binop.arg2); 1190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_Alu(aop, dst, argL, argR)); 1191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return dst; 1192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: break; 1194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 11966d67c5925dfb5eae9a15380403fa2a81e18a91eaBen Cheng /* SDIV/UDIV */ 11976d67c5925dfb5eae9a15380403fa2a81e18a91eaBen Cheng if (e->Iex.Binop.op == Iop_DivU32 || e->Iex.Binop.op == Iop_DivS32) { 11986d67c5925dfb5eae9a15380403fa2a81e18a91eaBen Cheng HReg dst = newVRegI(env); 11996d67c5925dfb5eae9a15380403fa2a81e18a91eaBen Cheng HReg argL = iselIntExpr_R(env, e->Iex.Binop.arg1); 12006d67c5925dfb5eae9a15380403fa2a81e18a91eaBen Cheng HReg argR = iselIntExpr_R(env, e->Iex.Binop.arg2); 12016d67c5925dfb5eae9a15380403fa2a81e18a91eaBen Cheng 12026d67c5925dfb5eae9a15380403fa2a81e18a91eaBen Cheng addInstr(env, 12036d67c5925dfb5eae9a15380403fa2a81e18a91eaBen Cheng ARMInstr_Div(e->Iex.Binop.op == Iop_DivU32 ? 12046d67c5925dfb5eae9a15380403fa2a81e18a91eaBen Cheng ARMdiv_U : ARMdiv_S, 12056d67c5925dfb5eae9a15380403fa2a81e18a91eaBen Cheng dst, argL, argR)); 12066d67c5925dfb5eae9a15380403fa2a81e18a91eaBen Cheng return dst; 12076d67c5925dfb5eae9a15380403fa2a81e18a91eaBen Cheng } 12086d67c5925dfb5eae9a15380403fa2a81e18a91eaBen Cheng 1209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* SHL/SHR/SAR */ 1210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (e->Iex.Binop.op) { 1211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Shl32: sop = ARMsh_SHL; goto sh_binop; 1212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Shr32: sop = ARMsh_SHR; goto sh_binop; 1213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Sar32: sop = ARMsh_SAR; goto sh_binop; 1214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sh_binop: { 1215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg dst = newVRegI(env); 1216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselIntExpr_R(env, e->Iex.Binop.arg1); 1217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ARMRI5* argR = iselIntExpr_RI5(env, e->Iex.Binop.arg2); 1218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_Shift(sop, dst, argL, argR)); 1219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert(ty == Ity_I32); /* else the IR is ill-typed */ 1220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return dst; 1221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: break; 1223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* MUL */ 1226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->Iex.Binop.op == Iop_Mul32) { 1227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselIntExpr_R(env, e->Iex.Binop.arg1); 1228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselIntExpr_R(env, e->Iex.Binop.arg2); 1229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg dst = newVRegI(env); 1230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, mk_iMOVds_RR(hregARM_R2(), argL)); 1231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, mk_iMOVds_RR(hregARM_R3(), argR)); 1232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_Mul(ARMmul_PLAIN)); 1233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, mk_iMOVds_RR(dst, hregARM_R0())); 1234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return dst; 1235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Handle misc other ops. */ 1238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->Iex.Binop.op == Iop_Max32U) { 1240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselIntExpr_R(env, e->Iex.Binop.arg1); 1241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselIntExpr_R(env, e->Iex.Binop.arg2); 1242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg dst = newVRegI(env); 1243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_CmpOrTst(True/*isCmp*/, argL, 1244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ARMRI84_R(argR))); 1245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, mk_iMOVds_RR(dst, argL)); 1246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_CMov(ARMcc_LO, dst, ARMRI84_R(argR))); 1247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return dst; 1248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->Iex.Binop.op == Iop_CmpF64) { 1251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg dL = iselDblExpr(env, e->Iex.Binop.arg1); 1252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg dR = iselDblExpr(env, e->Iex.Binop.arg2); 1253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg dst = newVRegI(env); 1254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Do the compare (FCMPD) and set NZCV in FPSCR. Then also do 1255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown FMSTAT, so we can examine the results directly. */ 1256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_VCmpD(dL, dR)); 1257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Create in dst, the IRCmpF64Result encoded result. */ 1258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_Imm32(dst, 0)); 1259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_CMov(ARMcc_EQ, dst, ARMRI84_I84(0x40,0))); //EQ 1260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_CMov(ARMcc_MI, dst, ARMRI84_I84(0x01,0))); //LT 1261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_CMov(ARMcc_GT, dst, ARMRI84_I84(0x00,0))); //GT 1262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_CMov(ARMcc_VS, dst, ARMRI84_I84(0x45,0))); //UN 1263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return dst; 1264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->Iex.Binop.op == Iop_F64toI32S 1267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown || e->Iex.Binop.op == Iop_F64toI32U) { 1268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Wretched uglyness all round, due to having to deal 1269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown with rounding modes. Oh well. */ 1270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* FIXME: if arg1 is a constant indicating round-to-zero, 1271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown then we could skip all this arsing around with FPSCR and 1272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown simply emit FTO{S,U}IZD. */ 1273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bool syned = e->Iex.Binop.op == Iop_F64toI32S; 1274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg valD = iselDblExpr(env, e->Iex.Binop.arg2); 1275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown set_VFP_rounding_mode(env, e->Iex.Binop.arg1); 1276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* FTO{S,U}ID valF, valD */ 1277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg valF = newVRegF(env); 1278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_VCvtID(False/*!iToD*/, syned, 1279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown valF, valD)); 1280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown set_VFP_rounding_default(env); 1281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* VMOV dst, valF */ 1282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg dst = newVRegI(env); 1283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_VXferS(False/*!toS*/, valF, dst)); 1284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return dst; 1285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->Iex.Binop.op == Iop_GetElem8x8 1288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown || e->Iex.Binop.op == Iop_GetElem16x4 1289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown || e->Iex.Binop.op == Iop_GetElem32x2) { 1290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegI(env); 1291663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng HReg arg = iselNeon64Expr(env, e->Iex.Binop.arg1); 1292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt index, size; 1293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->Iex.Binop.arg2->tag != Iex_Const || 1294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown typeOfIRExpr(env->type_env, e->Iex.Binop.arg2) != Ity_I8) { 1295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vpanic("ARM target supports GetElem with constant " 1296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "second argument only\n"); 1297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown index = e->Iex.Binop.arg2->Iex.Const.con->Ico.U8; 1299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (e->Iex.Binop.op) { 1300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_GetElem8x8: vassert(index < 8); size = 0; break; 1301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_GetElem16x4: vassert(index < 4); size = 1; break; 1302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_GetElem32x2: vassert(index < 2); size = 2; break; 1303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: vassert(0); 1304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnaryS(ARMneon_GETELEMS, 1306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mkARMNRS(ARMNRS_Reg, res, 0), 1307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mkARMNRS(ARMNRS_Scalar, arg, index), 1308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown size, False)); 1309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 1310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->Iex.Binop.op == Iop_GetElem8x16 1313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown || e->Iex.Binop.op == Iop_GetElem16x8 1314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown || e->Iex.Binop.op == Iop_GetElem32x4) { 1315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegI(env); 1316663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng HReg arg = iselNeonExpr(env, e->Iex.Binop.arg1); 1317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt index, size; 1318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->Iex.Binop.arg2->tag != Iex_Const || 1319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown typeOfIRExpr(env->type_env, e->Iex.Binop.arg2) != Ity_I8) { 1320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vpanic("ARM target supports GetElem with constant " 1321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "second argument only\n"); 1322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown index = e->Iex.Binop.arg2->Iex.Const.con->Ico.U8; 1324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (e->Iex.Binop.op) { 1325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_GetElem8x16: vassert(index < 16); size = 0; break; 1326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_GetElem16x8: vassert(index < 8); size = 1; break; 1327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_GetElem32x4: vassert(index < 4); size = 2; break; 1328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: vassert(0); 1329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnaryS(ARMneon_GETELEMS, 1331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mkARMNRS(ARMNRS_Reg, res, 0), 1332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mkARMNRS(ARMNRS_Scalar, arg, index), 1333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown size, True)); 1334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 1335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* All cases involving host-side helper calls. */ 1338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown void* fn = NULL; 1339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (e->Iex.Binop.op) { 1340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Add16x2: 1341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fn = &h_generic_calc_Add16x2; break; 1342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Sub16x2: 1343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fn = &h_generic_calc_Sub16x2; break; 1344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_HAdd16Ux2: 1345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fn = &h_generic_calc_HAdd16Ux2; break; 1346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_HAdd16Sx2: 1347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fn = &h_generic_calc_HAdd16Sx2; break; 1348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_HSub16Ux2: 1349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fn = &h_generic_calc_HSub16Ux2; break; 1350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_HSub16Sx2: 1351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fn = &h_generic_calc_HSub16Sx2; break; 1352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QAdd16Sx2: 1353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fn = &h_generic_calc_QAdd16Sx2; break; 1354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QSub16Sx2: 1355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fn = &h_generic_calc_QSub16Sx2; break; 1356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Add8x4: 1357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fn = &h_generic_calc_Add8x4; break; 1358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Sub8x4: 1359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fn = &h_generic_calc_Sub8x4; break; 1360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_HAdd8Ux4: 1361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fn = &h_generic_calc_HAdd8Ux4; break; 1362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_HAdd8Sx4: 1363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fn = &h_generic_calc_HAdd8Sx4; break; 1364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_HSub8Ux4: 1365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fn = &h_generic_calc_HSub8Ux4; break; 1366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_HSub8Sx4: 1367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fn = &h_generic_calc_HSub8Sx4; break; 1368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QAdd8Sx4: 1369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fn = &h_generic_calc_QAdd8Sx4; break; 1370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QAdd8Ux4: 1371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fn = &h_generic_calc_QAdd8Ux4; break; 1372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QSub8Sx4: 1373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fn = &h_generic_calc_QSub8Sx4; break; 1374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QSub8Ux4: 1375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fn = &h_generic_calc_QSub8Ux4; break; 1376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Sad8Ux4: 1377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fn = &h_generic_calc_Sad8Ux4; break; 1378663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng case Iop_QAdd32S: 1379663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng fn = &h_generic_calc_QAdd32S; break; 1380663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng case Iop_QSub32S: 1381663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng fn = &h_generic_calc_QSub32S; break; 1382663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng case Iop_QSub16Ux2: 1383663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng fn = &h_generic_calc_QSub16Ux2; break; 1384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: 1385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 1386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (fn) { 1389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg regL = iselIntExpr_R(env, e->Iex.Binop.arg1); 1390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg regR = iselIntExpr_R(env, e->Iex.Binop.arg2); 1391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegI(env); 1392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, mk_iMOVds_RR(hregARM_R0(), regL)); 1393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, mk_iMOVds_RR(hregARM_R1(), regR)); 1394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_Call( ARMcc_AL, (HWord)Ptr_to_ULong(fn), 2 )); 1395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, mk_iMOVds_RR(res, hregARM_R0())); 1396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 1397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 1400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* --------- UNARY OP --------- */ 1403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iex_Unop: { 1404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz /* 1Uto8(32to1(expr32)) */ 1406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz if (e->Iex.Unop.op == Iop_1Uto8) { 1407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz DECLARE_PATTERN(p_32to1_then_1Uto8); 1408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz DEFINE_PATTERN(p_32to1_then_1Uto8, 1409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz unop(Iop_1Uto8,unop(Iop_32to1,bind(0)))); 1410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz if (matchIRExpr(&mi,p_32to1_then_1Uto8,e)) { 1411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz IRExpr* expr32 = mi.bindee[0]; 1412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz HReg dst = newVRegI(env); 1413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz HReg src = iselIntExpr_R(env, expr32); 1414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz addInstr(env, mk_iMOVsd_RR(src,dst) ); 1415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz addInstr(env, X86Instr_Alu32R(Xalu_AND, 1416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz X86RMI_Imm(1), dst)); 1417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz return dst; 1418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz } 1419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz } 1420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz 1421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz /* 8Uto32(LDle(expr32)) */ 1422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz if (e->Iex.Unop.op == Iop_8Uto32) { 1423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz DECLARE_PATTERN(p_LDle8_then_8Uto32); 1424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz DEFINE_PATTERN(p_LDle8_then_8Uto32, 1425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz unop(Iop_8Uto32, 1426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz IRExpr_Load(Iend_LE,Ity_I8,bind(0))) ); 1427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz if (matchIRExpr(&mi,p_LDle8_then_8Uto32,e)) { 1428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz HReg dst = newVRegI(env); 1429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz X86AMode* amode = iselIntExpr_AMode ( env, mi.bindee[0] ); 1430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz addInstr(env, X86Instr_LoadEX(1,False,amode,dst)); 1431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz return dst; 1432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz } 1433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz } 1434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz 1435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz /* 8Sto32(LDle(expr32)) */ 1436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz if (e->Iex.Unop.op == Iop_8Sto32) { 1437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz DECLARE_PATTERN(p_LDle8_then_8Sto32); 1438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz DEFINE_PATTERN(p_LDle8_then_8Sto32, 1439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz unop(Iop_8Sto32, 1440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz IRExpr_Load(Iend_LE,Ity_I8,bind(0))) ); 1441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz if (matchIRExpr(&mi,p_LDle8_then_8Sto32,e)) { 1442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz HReg dst = newVRegI(env); 1443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz X86AMode* amode = iselIntExpr_AMode ( env, mi.bindee[0] ); 1444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz addInstr(env, X86Instr_LoadEX(1,True,amode,dst)); 1445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz return dst; 1446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz } 1447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz } 1448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz 1449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz /* 16Uto32(LDle(expr32)) */ 1450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz if (e->Iex.Unop.op == Iop_16Uto32) { 1451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz DECLARE_PATTERN(p_LDle16_then_16Uto32); 1452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz DEFINE_PATTERN(p_LDle16_then_16Uto32, 1453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz unop(Iop_16Uto32, 1454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz IRExpr_Load(Iend_LE,Ity_I16,bind(0))) ); 1455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz if (matchIRExpr(&mi,p_LDle16_then_16Uto32,e)) { 1456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz HReg dst = newVRegI(env); 1457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz X86AMode* amode = iselIntExpr_AMode ( env, mi.bindee[0] ); 1458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz addInstr(env, X86Instr_LoadEX(2,False,amode,dst)); 1459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz return dst; 1460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz } 1461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz } 1462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz 1463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz /* 8Uto32(GET:I8) */ 1464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz if (e->Iex.Unop.op == Iop_8Uto32) { 1465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz if (e->Iex.Unop.arg->tag == Iex_Get) { 1466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz HReg dst; 1467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz X86AMode* amode; 1468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz vassert(e->Iex.Unop.arg->Iex.Get.ty == Ity_I8); 1469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz dst = newVRegI(env); 1470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz amode = X86AMode_IR(e->Iex.Unop.arg->Iex.Get.offset, 1471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz hregX86_EBP()); 1472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz addInstr(env, X86Instr_LoadEX(1,False,amode,dst)); 1473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz return dst; 1474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz } 1475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz } 1476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz 1477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz /* 16to32(GET:I16) */ 1478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz if (e->Iex.Unop.op == Iop_16Uto32) { 1479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz if (e->Iex.Unop.arg->tag == Iex_Get) { 1480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz HReg dst; 1481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz X86AMode* amode; 1482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz vassert(e->Iex.Unop.arg->Iex.Get.ty == Ity_I16); 1483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz dst = newVRegI(env); 1484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz amode = X86AMode_IR(e->Iex.Unop.arg->Iex.Get.offset, 1485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz hregX86_EBP()); 1486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz addInstr(env, X86Instr_LoadEX(2,False,amode,dst)); 1487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz return dst; 1488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz } 1489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz } 1490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (e->Iex.Unop.op) { 1492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_8Uto32: { 1493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg dst = newVRegI(env); 1494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg src = iselIntExpr_R(env, e->Iex.Unop.arg); 1495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_Alu(ARMalu_AND, 1496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown dst, src, ARMRI84_I84(0xFF,0))); 1497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return dst; 1498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz case Iop_8Uto16: 1500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz case Iop_8Uto32: 1501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz case Iop_16Uto32: { 1502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz HReg dst = newVRegI(env); 1503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz HReg src = iselIntExpr_R(env, e->Iex.Unop.arg); 1504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz UInt mask = e->Iex.Unop.op==Iop_16Uto32 ? 0xFFFF : 0xFF; 1505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz addInstr(env, mk_iMOVsd_RR(src,dst) ); 1506ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz addInstr(env, X86Instr_Alu32R(Xalu_AND, 1507ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz X86RMI_Imm(mask), dst)); 1508ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz return dst; 1509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz } 1510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz case Iop_8Sto16: 1511ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz case Iop_8Sto32: 1512ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_16Uto32: { 1513ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg dst = newVRegI(env); 1514ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg src = iselIntExpr_R(env, e->Iex.Unop.arg); 1515ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ARMRI5* amt = ARMRI5_I5(16); 1516ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_Shift(ARMsh_SHL, dst, src, amt)); 1517ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_Shift(ARMsh_SHR, dst, dst, amt)); 1518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return dst; 1519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_8Sto32: 1521ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_16Sto32: { 1522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg dst = newVRegI(env); 1523ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg src = iselIntExpr_R(env, e->Iex.Unop.arg); 1524ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ARMRI5* amt = ARMRI5_I5(e->Iex.Unop.op==Iop_16Sto32 ? 16 : 24); 1525ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_Shift(ARMsh_SHL, dst, src, amt)); 1526ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_Shift(ARMsh_SAR, dst, dst, amt)); 1527ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return dst; 1528ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1529ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz case Iop_Not8: 1530ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz case Iop_Not16: 1531ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Not32: { 1532ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg dst = newVRegI(env); 1533ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg src = iselIntExpr_R(env, e->Iex.Unop.arg); 1534ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_Unary(ARMun_NOT, dst, src)); 1535ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return dst; 1536ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1537ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_64HIto32: { 1538ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg rHi, rLo; 1539ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown iselInt64Expr(&rHi,&rLo, env, e->Iex.Unop.arg); 1540ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return rHi; /* and abandon rLo .. poor wee thing :-) */ 1541ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1542ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_64to32: { 1543ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg rHi, rLo; 1544ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown iselInt64Expr(&rHi,&rLo, env, e->Iex.Unop.arg); 1545ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return rLo; /* similar stupid comment to the above ... */ 1546ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1547ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_64to8: { 1548ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg rHi, rLo; 1549663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng if (env->hwcaps & VEX_HWCAPS_ARM_NEON) { 1550ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg tHi = newVRegI(env); 1551ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg tLo = newVRegI(env); 1552ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg tmp = iselNeon64Expr(env, e->Iex.Unop.arg); 1553ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_VXferD(False, tmp, tHi, tLo)); 1554ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown rHi = tHi; 1555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown rLo = tLo; 1556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 1557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown iselInt64Expr(&rHi,&rLo, env, e->Iex.Unop.arg); 1558ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1559ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return rLo; 1560ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1561ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz case Iop_16HIto8: 1562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz case Iop_32HIto16: { 1563ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz HReg dst = newVRegI(env); 1564ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz HReg src = iselIntExpr_R(env, e->Iex.Unop.arg); 1565ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz Int shift = e->Iex.Unop.op == Iop_16HIto8 ? 8 : 16; 1566ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz addInstr(env, mk_iMOVsd_RR(src,dst) ); 1567ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz addInstr(env, X86Instr_Sh32(Xsh_SHR, shift, dst)); 1568ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz return dst; 1569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz } 1570ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_1Uto32: 1571ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_1Uto8: { 1572ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg dst = newVRegI(env); 1573ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ARMCondCode cond = iselCondCode(env, e->Iex.Unop.arg); 1574ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_Mov(dst, ARMRI84_I84(0,0))); 1575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_CMov(cond, dst, ARMRI84_I84(1,0))); 1576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return dst; 1577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_1Sto32: { 1580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg dst = newVRegI(env); 1581ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ARMCondCode cond = iselCondCode(env, e->Iex.Unop.arg); 1582ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ARMRI5* amt = ARMRI5_I5(31); 1583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* This is really rough. We could do much better here; 1584ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown perhaps mvn{cond} dst, #0 as the second insn? 1585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (same applies to 1Sto64) */ 1586ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_Mov(dst, ARMRI84_I84(0,0))); 1587ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_CMov(cond, dst, ARMRI84_I84(1,0))); 1588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_Shift(ARMsh_SHL, dst, dst, amt)); 1589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_Shift(ARMsh_SAR, dst, dst, amt)); 1590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return dst; 1591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz case Iop_1Sto8: 1595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz case Iop_1Sto16: 1596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz case Iop_1Sto32: { 1597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz /* could do better than this, but for now ... */ 1598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz HReg dst = newVRegI(env); 1599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz X86CondCode cond = iselCondCode(env, e->Iex.Unop.arg); 1600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz addInstr(env, X86Instr_Set32(cond,dst)); 1601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz addInstr(env, X86Instr_Sh32(Xsh_SHL, 31, dst)); 1602ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz addInstr(env, X86Instr_Sh32(Xsh_SAR, 31, dst)); 1603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz return dst; 1604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz } 1605ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz case Iop_Ctz32: { 1606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz /* Count trailing zeroes, implemented by x86 'bsfl' */ 1607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz HReg dst = newVRegI(env); 1608ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz HReg src = iselIntExpr_R(env, e->Iex.Unop.arg); 1609ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz addInstr(env, X86Instr_Bsfr32(True,src,dst)); 1610ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz return dst; 1611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz } 1612ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Clz32: { 1613ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Count leading zeroes; easy on ARM. */ 1614ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg dst = newVRegI(env); 1615ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg src = iselIntExpr_R(env, e->Iex.Unop.arg); 1616ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_Unary(ARMun_CLZ, dst, src)); 1617ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return dst; 1618ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1619ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1620ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CmpwNEZ32: { 1621ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg dst = newVRegI(env); 1622ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg src = iselIntExpr_R(env, e->Iex.Unop.arg); 1623ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_Unary(ARMun_NEG, dst, src)); 1624ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_Alu(ARMalu_OR, dst, dst, ARMRI84_R(src))); 1625ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_Shift(ARMsh_SAR, dst, dst, ARMRI5_I5(31))); 1626ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return dst; 1627ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1628ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1629ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Left32: { 1630ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg dst = newVRegI(env); 1631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg src = iselIntExpr_R(env, e->Iex.Unop.arg); 1632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_Unary(ARMun_NEG, dst, src)); 1633ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_Alu(ARMalu_OR, dst, dst, ARMRI84_R(src))); 1634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return dst; 1635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz case Iop_V128to32: { 1638ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz HReg dst = newVRegI(env); 1639ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz HReg vec = iselVecExpr(env, e->Iex.Unop.arg); 1640ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz X86AMode* esp0 = X86AMode_IR(0, hregX86_ESP()); 1641ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz sub_from_esp(env, 16); 1642ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz addInstr(env, X86Instr_SseLdSt(False/*store*/, vec, esp0)); 1643ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz addInstr(env, X86Instr_Alu32R( Xalu_MOV, X86RMI_Mem(esp0), dst )); 1644ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz add_to_esp(env, 16); 1645ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz return dst; 1646ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz } 1647ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz 1648ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_ReinterpF32asI32: { 1649ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg dst = newVRegI(env); 1650ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg src = iselFltExpr(env, e->Iex.Unop.arg); 1651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_VXferS(False/*!toS*/, src, dst)); 1652ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return dst; 1653ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1654ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1655ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz 1656ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz case Iop_16to8: 1657ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_32to8: 1658ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_32to16: 1659ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* These are no-ops. */ 1660ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return iselIntExpr_R(env, e->Iex.Unop.arg); 1661ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1662ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: 1663ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 1664ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1665ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1666ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* All Unop cases involving host-side helper calls. */ 1667ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown void* fn = NULL; 1668ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (e->Iex.Unop.op) { 1669ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CmpNEZ16x2: 1670ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fn = &h_generic_calc_CmpNEZ16x2; break; 1671ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CmpNEZ8x4: 1672ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fn = &h_generic_calc_CmpNEZ8x4; break; 1673ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: 1674ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 1675ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1676ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1677ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (fn) { 1678ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg arg = iselIntExpr_R(env, e->Iex.Unop.arg); 1679ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegI(env); 1680ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, mk_iMOVds_RR(hregARM_R0(), arg)); 1681ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_Call( ARMcc_AL, (HWord)Ptr_to_ULong(fn), 1 )); 1682ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, mk_iMOVds_RR(res, hregARM_R0())); 1683ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 1684ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1685ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1686ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 1687ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1688ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1689ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* --------- GET --------- */ 1690ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iex_Get: { 1691ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (ty == Ity_I32 1692ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && 0 == (e->Iex.Get.offset & 3) 1693ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && e->Iex.Get.offset < 4096-4) { 1694ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg dst = newVRegI(env); 1695ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_LdSt32( 1696ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown True/*isLoad*/, 1697ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown dst, 1698ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ARMAMode1_RI(hregARM_R8(), e->Iex.Get.offset))); 1699ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return dst; 1700ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1701ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz if (ty == Ity_I8 || ty == Ity_I16) { 1702ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz HReg dst = newVRegI(env); 1703ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz addInstr(env, X86Instr_LoadEX( 1704ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz toUChar(ty==Ity_I8 ? 1 : 2), 1705ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz False, 1706ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz X86AMode_IR(e->Iex.Get.offset,hregX86_EBP()), 1707ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz dst)); 1708ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz return dst; 1709ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz } 1710ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 1711ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1712ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1713ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz case Iex_GetI: { 1714ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz X86AMode* am 1715ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz = genGuestArrayOffset( 1716ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz env, e->Iex.GetI.descr, 1717ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz e->Iex.GetI.ix, e->Iex.GetI.bias ); 1718ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz HReg dst = newVRegI(env); 1719ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz if (ty == Ity_I8) { 1720ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz addInstr(env, X86Instr_LoadEX( 1, False, am, dst )); 1721ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz return dst; 1722ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz } 1723ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz if (ty == Ity_I32) { 1724ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz addInstr(env, X86Instr_Alu32R(Xalu_MOV, X86RMI_Mem(am), dst)); 1725ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz return dst; 1726ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz } 1727ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz break; 1728ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz } 1729ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1730ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* --------- CCALL --------- */ 1731ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iex_CCall: { 1732ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg dst = newVRegI(env); 1733ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert(ty == e->Iex.CCall.retty); 1734ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1735ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* be very restrictive for now. Only 32/64-bit ints allowed 1736ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for args, and 32 bits for return type. */ 1737ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->Iex.CCall.retty != Ity_I32) 1738ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown goto irreducible; 1739ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1740ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Marshal args, do the call, clear stack. */ 1741ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bool ok = doHelperCall( env, False, 1742ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown NULL, e->Iex.CCall.cee, e->Iex.CCall.args ); 1743ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (ok) { 1744ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, mk_iMOVds_RR(dst, hregARM_R0())); 1745ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return dst; 1746ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1747ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* else fall through; will hit the irreducible: label */ 1748ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1749ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1750ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* --------- LITERAL --------- */ 1751ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* 32 literals */ 1752ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iex_Const: { 1753ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt u = 0; 1754ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg dst = newVRegI(env); 1755ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (e->Iex.Const.con->tag) { 1756ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Ico_U32: u = e->Iex.Const.con->Ico.U32; break; 1757ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Ico_U16: u = 0xFFFF & (e->Iex.Const.con->Ico.U16); break; 1758ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Ico_U8: u = 0xFF & (e->Iex.Const.con->Ico.U8); break; 1759ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: ppIRExpr(e); vpanic("iselIntExpr_R.Iex_Const(arm)"); 1760ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1761ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_Imm32(dst, u)); 1762ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return dst; 1763ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1764ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1765ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* --------- MULTIPLEX --------- */ 1766ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iex_Mux0X: { 1767ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRExpr* cond = e->Iex.Mux0X.cond; 1768ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1769ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Mux0X( 32to8(1Uto32(ccexpr)), expr0, exprX ) */ 1770ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (ty == Ity_I32 1771ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && cond->tag == Iex_Unop 1772ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && cond->Iex.Unop.op == Iop_32to8 1773ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && cond->Iex.Unop.arg->tag == Iex_Unop 1774ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && cond->Iex.Unop.arg->Iex.Unop.op == Iop_1Uto32) { 1775ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ARMCondCode cc; 1776ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg rX = iselIntExpr_R(env, e->Iex.Mux0X.exprX); 1777ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ARMRI84* r0 = iselIntExpr_RI84(NULL, False, env, e->Iex.Mux0X.expr0); 1778ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg dst = newVRegI(env); 1779ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, mk_iMOVds_RR(dst, rX)); 1780ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown cc = iselCondCode(env, cond->Iex.Unop.arg->Iex.Unop.arg); 1781ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_CMov(cc ^ 1, dst, r0)); 1782ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return dst; 1783ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1784ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1785ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Mux0X(cond, expr0, exprX) (general case) */ 1786ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (ty == Ity_I32) { 1787ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg r8; 1788ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg rX = iselIntExpr_R(env, e->Iex.Mux0X.exprX); 1789ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ARMRI84* r0 = iselIntExpr_RI84(NULL, False, env, e->Iex.Mux0X.expr0); 1790ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg dst = newVRegI(env); 1791ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, mk_iMOVds_RR(dst, rX)); 1792ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown r8 = iselIntExpr_R(env, cond); 1793ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_CmpOrTst(False/*!isCmp*/, r8, 1794ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ARMRI84_I84(0xFF,0))); 1795ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_CMov(ARMcc_EQ, dst, r0)); 1796ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return dst; 1797ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1798ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 1799ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1800ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1801ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: 1802ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 1803ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } /* switch (e->tag) */ 1804ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1805ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* We get here if no pattern matched. */ 1806ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown irreducible: 1807ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ppIRExpr(e); 1808ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vpanic("iselIntExpr_R: cannot reduce tree"); 1809ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1810ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1811ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1812ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* -------------------- 64-bit -------------------- */ 1813ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1814ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Compute a 64-bit value into a register pair, which is returned as 1815ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown the first two parameters. As with iselIntExpr_R, these may be 1816ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown either real or virtual regs; in any case they must not be changed 1817ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown by subsequent code emitted by the caller. */ 1818ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1819ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void iselInt64Expr ( HReg* rHi, HReg* rLo, ISelEnv* env, IRExpr* e ) 1820ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1821ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown iselInt64Expr_wrk(rHi, rLo, env, e); 1822ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# if 0 1823ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vex_printf("\n"); ppIRExpr(e); vex_printf("\n"); 1824ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 1825ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert(hregClass(*rHi) == HRcInt32); 1826ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert(hregIsVirtual(*rHi)); 1827ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert(hregClass(*rLo) == HRcInt32); 1828ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert(hregIsVirtual(*rLo)); 1829ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1830ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1831ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* DO NOT CALL THIS DIRECTLY ! */ 1832ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void iselInt64Expr_wrk ( HReg* rHi, HReg* rLo, ISelEnv* env, IRExpr* e ) 1833ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1834ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert(e); 1835ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert(typeOfIRExpr(env->type_env,e) == Ity_I64); 1836ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1837ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* 64-bit literal */ 1838ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->tag == Iex_Const) { 1839ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ULong w64 = e->Iex.Const.con->Ico.U64; 1840ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt wHi = toUInt(w64 >> 32); 1841ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt wLo = toUInt(w64); 1842ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg tHi = newVRegI(env); 1843ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg tLo = newVRegI(env); 1844ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert(e->Iex.Const.con->tag == Ico_U64); 1845ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_Imm32(tHi, wHi)); 1846ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_Imm32(tLo, wLo)); 1847ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *rHi = tHi; 1848ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *rLo = tLo; 1849ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return; 1850ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1851ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1852ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* read 64-bit IRTemp */ 1853ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->tag == Iex_RdTmp) { 1854663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng if (env->hwcaps & VEX_HWCAPS_ARM_NEON) { 1855ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg tHi = newVRegI(env); 1856ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg tLo = newVRegI(env); 1857ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg tmp = iselNeon64Expr(env, e); 1858ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_VXferD(False, tmp, tHi, tLo)); 1859ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *rHi = tHi; 1860ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *rLo = tLo; 1861ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 1862ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown lookupIRTemp64( rHi, rLo, env, e->Iex.RdTmp.tmp); 1863ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1864ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return; 1865ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1866ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1867ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* 64-bit load */ 1868ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->tag == Iex_Load && e->Iex.Load.end == Iend_LE) { 1869ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg tLo, tHi, rA; 1870ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert(e->Iex.Load.ty == Ity_I64); 1871ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown rA = iselIntExpr_R(env, e->Iex.Load.addr); 1872ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tHi = newVRegI(env); 1873ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tLo = newVRegI(env); 1874ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_LdSt32(True/*isLoad*/, tHi, ARMAMode1_RI(rA, 4))); 1875ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_LdSt32(True/*isLoad*/, tLo, ARMAMode1_RI(rA, 0))); 1876ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *rHi = tHi; 1877ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *rLo = tLo; 1878ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return; 1879ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1880ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1881ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* 64-bit GET */ 1882ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->tag == Iex_Get) { 1883ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ARMAMode1* am0 = ARMAMode1_RI(hregARM_R8(), e->Iex.Get.offset + 0); 1884ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ARMAMode1* am4 = ARMAMode1_RI(hregARM_R8(), e->Iex.Get.offset + 4); 1885ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg tHi = newVRegI(env); 1886ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg tLo = newVRegI(env); 1887ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_LdSt32(True/*isLoad*/, tHi, am4)); 1888ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_LdSt32(True/*isLoad*/, tLo, am0)); 1889ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *rHi = tHi; 1890ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *rLo = tLo; 1891ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return; 1892ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1893ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1894ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* --------- BINARY ops --------- */ 1895ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->tag == Iex_Binop) { 1896ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (e->Iex.Binop.op) { 1897ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1898ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* 32 x 32 -> 64 multiply */ 1899ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_MullS32: 1900ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_MullU32: { 1901ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselIntExpr_R(env, e->Iex.Binop.arg1); 1902ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselIntExpr_R(env, e->Iex.Binop.arg2); 1903ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg tHi = newVRegI(env); 1904ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg tLo = newVRegI(env); 19056d67c5925dfb5eae9a15380403fa2a81e18a91eaBen Cheng ARMMulDivOp mop = e->Iex.Binop.op == Iop_MullS32 1906ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ? ARMmul_SX : ARMmul_ZX; 1907ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, mk_iMOVds_RR(hregARM_R2(), argL)); 1908ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, mk_iMOVds_RR(hregARM_R3(), argR)); 1909ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_Mul(mop)); 1910ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, mk_iMOVds_RR(tHi, hregARM_R1())); 1911ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, mk_iMOVds_RR(tLo, hregARM_R0())); 1912ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *rHi = tHi; 1913ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *rLo = tLo; 1914ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return; 1915ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1916ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1917ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Or64: { 1918ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg xLo, xHi, yLo, yHi; 1919ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg tHi = newVRegI(env); 1920ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg tLo = newVRegI(env); 1921ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown iselInt64Expr(&xHi, &xLo, env, e->Iex.Binop.arg1); 1922ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown iselInt64Expr(&yHi, &yLo, env, e->Iex.Binop.arg2); 1923ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_Alu(ARMalu_OR, tHi, xHi, ARMRI84_R(yHi))); 1924ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_Alu(ARMalu_OR, tLo, xLo, ARMRI84_R(yLo))); 1925ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *rHi = tHi; 1926ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *rLo = tLo; 1927ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return; 1928ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1929ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1930ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Add64: { 1931ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg xLo, xHi, yLo, yHi; 1932ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg tHi = newVRegI(env); 1933ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg tLo = newVRegI(env); 1934ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown iselInt64Expr(&xHi, &xLo, env, e->Iex.Binop.arg1); 1935ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown iselInt64Expr(&yHi, &yLo, env, e->Iex.Binop.arg2); 1936ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_Alu(ARMalu_ADDS, tLo, xLo, ARMRI84_R(yLo))); 1937ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_Alu(ARMalu_ADC, tHi, xHi, ARMRI84_R(yHi))); 1938ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *rHi = tHi; 1939ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *rLo = tLo; 1940ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return; 1941ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1942ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1943ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* 32HLto64(e1,e2) */ 1944ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_32HLto64: { 1945ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *rHi = iselIntExpr_R(env, e->Iex.Binop.arg1); 1946ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *rLo = iselIntExpr_R(env, e->Iex.Binop.arg2); 1947ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return; 1948ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1949ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1950ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: 1951ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 1952ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1953ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1954ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1955ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* --------- UNARY ops --------- */ 1956ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->tag == Iex_Unop) { 1957ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (e->Iex.Unop.op) { 1958ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1959ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* ReinterpF64asI64 */ 1960ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_ReinterpF64asI64: { 1961ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg dstHi = newVRegI(env); 1962ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg dstLo = newVRegI(env); 1963ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg src = iselDblExpr(env, e->Iex.Unop.arg); 1964ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_VXferD(False/*!toD*/, src, dstHi, dstLo)); 1965ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *rHi = dstHi; 1966ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *rLo = dstLo; 1967ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return; 1968ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1969ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1970ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Left64(e) */ 1971ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Left64: { 1972ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg yLo, yHi; 1973ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg tHi = newVRegI(env); 1974ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg tLo = newVRegI(env); 1975ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg zero = newVRegI(env); 1976ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* yHi:yLo = arg */ 1977ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown iselInt64Expr(&yHi, &yLo, env, e->Iex.Unop.arg); 1978ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* zero = 0 */ 1979ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_Imm32(zero, 0)); 1980ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* tLo = 0 - yLo, and set carry */ 1981ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_Alu(ARMalu_SUBS, 1982ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tLo, zero, ARMRI84_R(yLo))); 1983ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* tHi = 0 - yHi - carry */ 1984ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_Alu(ARMalu_SBC, 1985ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tHi, zero, ARMRI84_R(yHi))); 1986ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* So now we have tHi:tLo = -arg. To finish off, or 'arg' 1987ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown back in, so as to give the final result 1988ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tHi:tLo = arg | -arg. */ 1989ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_Alu(ARMalu_OR, tHi, tHi, ARMRI84_R(yHi))); 1990ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_Alu(ARMalu_OR, tLo, tLo, ARMRI84_R(yLo))); 1991ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *rHi = tHi; 1992ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *rLo = tLo; 1993ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return; 1994ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1995ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1996ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* CmpwNEZ64(e) */ 1997ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CmpwNEZ64: { 1998ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg srcLo, srcHi; 1999ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg tmp1 = newVRegI(env); 2000ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg tmp2 = newVRegI(env); 2001ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* srcHi:srcLo = arg */ 2002ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown iselInt64Expr(&srcHi, &srcLo, env, e->Iex.Unop.arg); 2003ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* tmp1 = srcHi | srcLo */ 2004ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_Alu(ARMalu_OR, 2005ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tmp1, srcHi, ARMRI84_R(srcLo))); 2006ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* tmp2 = (tmp1 | -tmp1) >>s 31 */ 2007ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_Unary(ARMun_NEG, tmp2, tmp1)); 2008ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_Alu(ARMalu_OR, 2009ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tmp2, tmp2, ARMRI84_R(tmp1))); 2010ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_Shift(ARMsh_SAR, 2011ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tmp2, tmp2, ARMRI5_I5(31))); 2012ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *rHi = tmp2; 2013ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *rLo = tmp2; 2014ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return; 2015ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2016ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2017ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_1Sto64: { 2018ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg dst = newVRegI(env); 2019ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ARMCondCode cond = iselCondCode(env, e->Iex.Unop.arg); 2020ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ARMRI5* amt = ARMRI5_I5(31); 2021ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* This is really rough. We could do much better here; 2022ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown perhaps mvn{cond} dst, #0 as the second insn? 2023ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (same applies to 1Sto32) */ 2024ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_Mov(dst, ARMRI84_I84(0,0))); 2025ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_CMov(cond, dst, ARMRI84_I84(1,0))); 2026ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_Shift(ARMsh_SHL, dst, dst, amt)); 2027ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_Shift(ARMsh_SAR, dst, dst, amt)); 2028ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *rHi = dst; 2029ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *rLo = dst; 2030ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return; 2031ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2032ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2033ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: 2034ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 2035ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2036ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } /* if (e->tag == Iex_Unop) */ 2037ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2038ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* --------- MULTIPLEX --------- */ 2039ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->tag == Iex_Mux0X) { 2040ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRType ty8; 2041ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg r8, rXhi, rXlo, r0hi, r0lo, dstHi, dstLo; 2042ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ty8 = typeOfIRExpr(env->type_env,e->Iex.Mux0X.cond); 2043ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert(ty8 == Ity_I8); 2044ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown iselInt64Expr(&rXhi, &rXlo, env, e->Iex.Mux0X.exprX); 2045ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown iselInt64Expr(&r0hi, &r0lo, env, e->Iex.Mux0X.expr0); 2046ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown dstHi = newVRegI(env); 2047ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown dstLo = newVRegI(env); 2048ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, mk_iMOVds_RR(dstHi, rXhi)); 2049ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, mk_iMOVds_RR(dstLo, rXlo)); 2050ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown r8 = iselIntExpr_R(env, e->Iex.Mux0X.cond); 2051ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_CmpOrTst(False/*!isCmp*/, r8, 2052ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ARMRI84_I84(0xFF,0))); 2053ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_CMov(ARMcc_EQ, dstHi, ARMRI84_R(r0hi))); 2054ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_CMov(ARMcc_EQ, dstLo, ARMRI84_R(r0lo))); 2055ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *rHi = dstHi; 2056ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *rLo = dstLo; 2057ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return; 2058ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2059ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2060ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* It is convenient sometimes to call iselInt64Expr even when we 2061ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown have NEON support (e.g. in do_helper_call we need 64-bit 2062ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown arguments as 2 x 32 regs). */ 2063663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng if (env->hwcaps & VEX_HWCAPS_ARM_NEON) { 2064ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg tHi = newVRegI(env); 2065ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg tLo = newVRegI(env); 2066ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg tmp = iselNeon64Expr(env, e); 2067ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_VXferD(False, tmp, tHi, tLo)); 2068ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *rHi = tHi; 2069ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *rLo = tLo; 2070ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return ; 2071ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2072ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2073ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ppIRExpr(e); 2074ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vpanic("iselInt64Expr"); 2075ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 2076ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2077ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2078ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------*/ 2079ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- ISEL: Vector (NEON) expressions (64 or 128 bit) ---*/ 2080ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------*/ 2081ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2082ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic HReg iselNeon64Expr ( ISelEnv* env, IRExpr* e ) 2083ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 2084ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg r = iselNeon64Expr_wrk( env, e ); 2085ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert(hregClass(r) == HRcFlt64); 2086ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert(hregIsVirtual(r)); 2087ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return r; 2088ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 2089ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2090ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* DO NOT CALL THIS DIRECTLY */ 2091ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic HReg iselNeon64Expr_wrk ( ISelEnv* env, IRExpr* e ) 2092ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 2093ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRType ty = typeOfIRExpr(env->type_env, e); 2094ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown MatchInfo mi; 2095ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert(e); 2096ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert(ty == Ity_I64); 2097ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2098ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->tag == Iex_RdTmp) { 2099ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return lookupIRTemp(env, e->Iex.RdTmp.tmp); 2100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->tag == Iex_Const) { 2103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg rLo, rHi; 2104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegD(env); 2105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown iselInt64Expr(&rHi, &rLo, env, e); 2106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_VXferD(True/*toD*/, res, rHi, rLo)); 2107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 2108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* 64-bit load */ 2111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->tag == Iex_Load && e->Iex.Load.end == Iend_LE) { 2112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegD(env); 2113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ARMAModeN* am = iselIntExpr_AModeN(env, e->Iex.Load.addr); 2114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert(ty == Ity_I64); 2115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NLdStD(True, res, am)); 2116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 2117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* 64-bit GET */ 2120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->tag == Iex_Get) { 2121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg addr = newVRegI(env); 2122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegD(env); 2123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert(ty == Ity_I64); 2124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_Add32(addr, hregARM_R8(), e->Iex.Get.offset)); 2125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NLdStD(True, res, mkARMAModeN_R(addr))); 2126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 2127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* --------- BINARY ops --------- */ 2130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->tag == Iex_Binop) { 2131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (e->Iex.Binop.op) { 2132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* 32 x 32 -> 64 multiply */ 2134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_MullS32: 2135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_MullU32: { 2136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg rLo, rHi; 2137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegD(env); 2138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown iselInt64Expr(&rHi, &rLo, env, e); 2139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_VXferD(True/*toD*/, res, rHi, rLo)); 2140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 2141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_And64: { 2144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegD(env); 2145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeon64Expr(env, e->Iex.Binop.arg1); 2146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeon64Expr(env, e->Iex.Binop.arg2); 2147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NBinary(ARMneon_VAND, 2148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, argR, 4, False)); 2149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 2150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Or64: { 2152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegD(env); 2153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeon64Expr(env, e->Iex.Binop.arg1); 2154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeon64Expr(env, e->Iex.Binop.arg2); 2155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NBinary(ARMneon_VORR, 2156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, argR, 4, False)); 2157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 2158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Xor64: { 2160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegD(env); 2161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeon64Expr(env, e->Iex.Binop.arg1); 2162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeon64Expr(env, e->Iex.Binop.arg2); 2163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NBinary(ARMneon_VXOR, 2164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, argR, 4, False)); 2165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 2166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* 32HLto64(e1,e2) */ 2169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_32HLto64: { 2170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg rHi = iselIntExpr_R(env, e->Iex.Binop.arg1); 2171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg rLo = iselIntExpr_R(env, e->Iex.Binop.arg2); 2172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegD(env); 2173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_VXferD(True/*toD*/, res, rHi, rLo)); 2174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 2175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Add8x8: 2178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Add16x4: 2179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Add32x2: 2180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Add64: { 2181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegD(env); 2182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeon64Expr(env, e->Iex.Binop.arg1); 2183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeon64Expr(env, e->Iex.Binop.arg2); 2184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size; 2185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (e->Iex.Binop.op) { 2186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Add8x8: size = 0; break; 2187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Add16x4: size = 1; break; 2188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Add32x2: size = 2; break; 2189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Add64: size = 3; break; 2190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: vassert(0); 2191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NBinary(ARMneon_VADD, 2193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, argR, size, False)); 2194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 2195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Add32Fx2: { 2197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegD(env); 2198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeon64Expr(env, e->Iex.Binop.arg1); 2199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeon64Expr(env, e->Iex.Binop.arg2); 2200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size = 0; 2201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NBinary(ARMneon_VADDFP, 2202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, argR, size, False)); 2203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 2204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Recps32Fx2: { 2206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegD(env); 2207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeon64Expr(env, e->Iex.Binop.arg1); 2208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeon64Expr(env, e->Iex.Binop.arg2); 2209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size = 0; 2210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NBinary(ARMneon_VRECPS, 2211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, argR, size, False)); 2212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 2213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Rsqrts32Fx2: { 2215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegD(env); 2216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeon64Expr(env, e->Iex.Binop.arg1); 2217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeon64Expr(env, e->Iex.Binop.arg2); 2218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size = 0; 2219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NBinary(ARMneon_VRSQRTS, 2220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, argR, size, False)); 2221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 2222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_InterleaveOddLanes8x8: 2224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_InterleaveOddLanes16x4: 2225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_InterleaveLO32x2: 2226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_InterleaveEvenLanes8x8: 2227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_InterleaveEvenLanes16x4: 2228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_InterleaveHI32x2: { 2229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg tmp = newVRegD(env); 2230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegD(env); 2231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeon64Expr(env, e->Iex.Binop.arg1); 2232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeon64Expr(env, e->Iex.Binop.arg2); 2233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size; 2234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt is_lo; 2235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (e->Iex.Binop.op) { 2236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_InterleaveOddLanes8x8: is_lo = 1; size = 0; break; 2237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_InterleaveEvenLanes8x8: is_lo = 0; size = 0; break; 2238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_InterleaveOddLanes16x4: is_lo = 1; size = 1; break; 2239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_InterleaveEvenLanes16x4: is_lo = 0; size = 1; break; 2240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_InterleaveLO32x2: is_lo = 1; size = 2; break; 2241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_InterleaveHI32x2: is_lo = 0; size = 2; break; 2242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: vassert(0); 2243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (is_lo) { 2245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnary(ARMneon_COPY, 2246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tmp, argL, 4, False)); 2247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnary(ARMneon_COPY, 2248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argR, 4, False)); 2249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NDual(ARMneon_TRN, 2250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, tmp, size, False)); 2251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 2252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnary(ARMneon_COPY, 2253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tmp, argR, 4, False)); 2254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnary(ARMneon_COPY, 2255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, 4, False)); 2256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NDual(ARMneon_TRN, 2257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tmp, res, size, False)); 2258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 2260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_InterleaveHI8x8: 2262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_InterleaveHI16x4: 2263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_InterleaveLO8x8: 2264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_InterleaveLO16x4: { 2265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg tmp = newVRegD(env); 2266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegD(env); 2267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeon64Expr(env, e->Iex.Binop.arg1); 2268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeon64Expr(env, e->Iex.Binop.arg2); 2269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size; 2270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt is_lo; 2271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (e->Iex.Binop.op) { 2272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_InterleaveHI8x8: is_lo = 1; size = 0; break; 2273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_InterleaveLO8x8: is_lo = 0; size = 0; break; 2274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_InterleaveHI16x4: is_lo = 1; size = 1; break; 2275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_InterleaveLO16x4: is_lo = 0; size = 1; break; 2276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: vassert(0); 2277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (is_lo) { 2279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnary(ARMneon_COPY, 2280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tmp, argL, 4, False)); 2281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnary(ARMneon_COPY, 2282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argR, 4, False)); 2283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NDual(ARMneon_ZIP, 2284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, tmp, size, False)); 2285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 2286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnary(ARMneon_COPY, 2287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tmp, argR, 4, False)); 2288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnary(ARMneon_COPY, 2289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, 4, False)); 2290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NDual(ARMneon_ZIP, 2291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tmp, res, size, False)); 2292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 2294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CatOddLanes8x8: 2296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CatOddLanes16x4: 2297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CatEvenLanes8x8: 2298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CatEvenLanes16x4: { 2299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg tmp = newVRegD(env); 2300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegD(env); 2301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeon64Expr(env, e->Iex.Binop.arg1); 2302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeon64Expr(env, e->Iex.Binop.arg2); 2303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size; 2304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt is_lo; 2305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (e->Iex.Binop.op) { 2306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CatOddLanes8x8: is_lo = 1; size = 0; break; 2307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CatEvenLanes8x8: is_lo = 0; size = 0; break; 2308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CatOddLanes16x4: is_lo = 1; size = 1; break; 2309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CatEvenLanes16x4: is_lo = 0; size = 1; break; 2310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: vassert(0); 2311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (is_lo) { 2313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnary(ARMneon_COPY, 2314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tmp, argL, 4, False)); 2315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnary(ARMneon_COPY, 2316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argR, 4, False)); 2317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NDual(ARMneon_UZP, 2318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, tmp, size, False)); 2319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 2320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnary(ARMneon_COPY, 2321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tmp, argR, 4, False)); 2322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnary(ARMneon_COPY, 2323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, 4, False)); 2324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NDual(ARMneon_UZP, 2325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tmp, res, size, False)); 2326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 2328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QAdd8Ux8: 2330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QAdd16Ux4: 2331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QAdd32Ux2: 2332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QAdd64Ux1: { 2333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegD(env); 2334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeon64Expr(env, e->Iex.Binop.arg1); 2335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeon64Expr(env, e->Iex.Binop.arg2); 2336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size; 2337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (e->Iex.Binop.op) { 2338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QAdd8Ux8: size = 0; break; 2339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QAdd16Ux4: size = 1; break; 2340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QAdd32Ux2: size = 2; break; 2341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QAdd64Ux1: size = 3; break; 2342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: vassert(0); 2343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NBinary(ARMneon_VQADDU, 2345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, argR, size, False)); 2346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 2347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QAdd8Sx8: 2349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QAdd16Sx4: 2350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QAdd32Sx2: 2351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QAdd64Sx1: { 2352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegD(env); 2353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeon64Expr(env, e->Iex.Binop.arg1); 2354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeon64Expr(env, e->Iex.Binop.arg2); 2355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size; 2356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (e->Iex.Binop.op) { 2357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QAdd8Sx8: size = 0; break; 2358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QAdd16Sx4: size = 1; break; 2359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QAdd32Sx2: size = 2; break; 2360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QAdd64Sx1: size = 3; break; 2361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: vassert(0); 2362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NBinary(ARMneon_VQADDS, 2364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, argR, size, False)); 2365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 2366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Sub8x8: 2368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Sub16x4: 2369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Sub32x2: 2370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Sub64: { 2371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegD(env); 2372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeon64Expr(env, e->Iex.Binop.arg1); 2373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeon64Expr(env, e->Iex.Binop.arg2); 2374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size; 2375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (e->Iex.Binop.op) { 2376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Sub8x8: size = 0; break; 2377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Sub16x4: size = 1; break; 2378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Sub32x2: size = 2; break; 2379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Sub64: size = 3; break; 2380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: vassert(0); 2381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NBinary(ARMneon_VSUB, 2383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, argR, size, False)); 2384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 2385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Sub32Fx2: { 2387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegD(env); 2388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeon64Expr(env, e->Iex.Binop.arg1); 2389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeon64Expr(env, e->Iex.Binop.arg2); 2390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size = 0; 2391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NBinary(ARMneon_VSUBFP, 2392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, argR, size, False)); 2393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 2394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QSub8Ux8: 2396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QSub16Ux4: 2397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QSub32Ux2: 2398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QSub64Ux1: { 2399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegD(env); 2400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeon64Expr(env, e->Iex.Binop.arg1); 2401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeon64Expr(env, e->Iex.Binop.arg2); 2402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size; 2403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (e->Iex.Binop.op) { 2404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QSub8Ux8: size = 0; break; 2405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QSub16Ux4: size = 1; break; 2406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QSub32Ux2: size = 2; break; 2407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QSub64Ux1: size = 3; break; 2408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: vassert(0); 2409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NBinary(ARMneon_VQSUBU, 2411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, argR, size, False)); 2412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 2413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QSub8Sx8: 2415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QSub16Sx4: 2416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QSub32Sx2: 2417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QSub64Sx1: { 2418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegD(env); 2419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeon64Expr(env, e->Iex.Binop.arg1); 2420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeon64Expr(env, e->Iex.Binop.arg2); 2421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size; 2422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (e->Iex.Binop.op) { 2423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QSub8Sx8: size = 0; break; 2424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QSub16Sx4: size = 1; break; 2425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QSub32Sx2: size = 2; break; 2426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QSub64Sx1: size = 3; break; 2427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: vassert(0); 2428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NBinary(ARMneon_VQSUBS, 2430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, argR, size, False)); 2431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 2432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Max8Ux8: 2434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Max16Ux4: 2435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Max32Ux2: { 2436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegD(env); 2437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeon64Expr(env, e->Iex.Binop.arg1); 2438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeon64Expr(env, e->Iex.Binop.arg2); 2439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size; 2440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (e->Iex.Binop.op) { 2441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Max8Ux8: size = 0; break; 2442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Max16Ux4: size = 1; break; 2443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Max32Ux2: size = 2; break; 2444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: vassert(0); 2445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NBinary(ARMneon_VMAXU, 2447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, argR, size, False)); 2448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 2449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Max8Sx8: 2451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Max16Sx4: 2452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Max32Sx2: { 2453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegD(env); 2454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeon64Expr(env, e->Iex.Binop.arg1); 2455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeon64Expr(env, e->Iex.Binop.arg2); 2456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size; 2457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (e->Iex.Binop.op) { 2458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Max8Sx8: size = 0; break; 2459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Max16Sx4: size = 1; break; 2460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Max32Sx2: size = 2; break; 2461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: vassert(0); 2462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NBinary(ARMneon_VMAXS, 2464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, argR, size, False)); 2465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 2466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Min8Ux8: 2468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Min16Ux4: 2469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Min32Ux2: { 2470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegD(env); 2471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeon64Expr(env, e->Iex.Binop.arg1); 2472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeon64Expr(env, e->Iex.Binop.arg2); 2473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size; 2474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (e->Iex.Binop.op) { 2475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Min8Ux8: size = 0; break; 2476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Min16Ux4: size = 1; break; 2477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Min32Ux2: size = 2; break; 2478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: vassert(0); 2479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NBinary(ARMneon_VMINU, 2481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, argR, size, False)); 2482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 2483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Min8Sx8: 2485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Min16Sx4: 2486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Min32Sx2: { 2487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegD(env); 2488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeon64Expr(env, e->Iex.Binop.arg1); 2489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeon64Expr(env, e->Iex.Binop.arg2); 2490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size; 2491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (e->Iex.Binop.op) { 2492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Min8Sx8: size = 0; break; 2493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Min16Sx4: size = 1; break; 2494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Min32Sx2: size = 2; break; 2495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: vassert(0); 2496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NBinary(ARMneon_VMINS, 2498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, argR, size, False)); 2499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 2500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Sar8x8: 2502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Sar16x4: 2503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Sar32x2: { 2504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegD(env); 2505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeon64Expr(env, e->Iex.Binop.arg1); 2506ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeon64Expr(env, e->Iex.Binop.arg2); 2507ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR2 = newVRegD(env); 2508ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg zero = newVRegD(env); 2509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size; 2510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (e->Iex.Binop.op) { 2511ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Sar8x8: size = 0; break; 2512ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Sar16x4: size = 1; break; 2513ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Sar32x2: size = 2; break; 2514ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Sar64: size = 3; break; 2515ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: vassert(0); 2516ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2517ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NeonImm(zero, ARMNImm_TI(0,0))); 2518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NBinary(ARMneon_VSUB, 2519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown argR2, zero, argR, size, False)); 2520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NShift(ARMneon_VSAL, 2521ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, argR2, size, False)); 2522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 2523ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2524ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Sal8x8: 2525ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Sal16x4: 2526ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Sal32x2: 2527ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Sal64x1: { 2528ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegD(env); 2529ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeon64Expr(env, e->Iex.Binop.arg1); 2530ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeon64Expr(env, e->Iex.Binop.arg2); 2531ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size; 2532ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (e->Iex.Binop.op) { 2533ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Sal8x8: size = 0; break; 2534ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Sal16x4: size = 1; break; 2535ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Sal32x2: size = 2; break; 2536ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Sal64x1: size = 3; break; 2537ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: vassert(0); 2538ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2539ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NShift(ARMneon_VSAL, 2540ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, argR, size, False)); 2541ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 2542ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2543ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Shr8x8: 2544ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Shr16x4: 2545ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Shr32x2: { 2546ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegD(env); 2547ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeon64Expr(env, e->Iex.Binop.arg1); 2548ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeon64Expr(env, e->Iex.Binop.arg2); 2549ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR2 = newVRegD(env); 2550ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg zero = newVRegD(env); 2551ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size; 2552ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (e->Iex.Binop.op) { 2553ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Shr8x8: size = 0; break; 2554ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Shr16x4: size = 1; break; 2555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Shr32x2: size = 2; break; 2556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: vassert(0); 2557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2558ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NeonImm(zero, ARMNImm_TI(0,0))); 2559ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NBinary(ARMneon_VSUB, 2560ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown argR2, zero, argR, size, False)); 2561ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NShift(ARMneon_VSHL, 2562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, argR2, size, False)); 2563ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 2564ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2565ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Shl8x8: 2566ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Shl16x4: 2567ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Shl32x2: { 2568ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegD(env); 2569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeon64Expr(env, e->Iex.Binop.arg1); 2570ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeon64Expr(env, e->Iex.Binop.arg2); 2571ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size; 2572ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (e->Iex.Binop.op) { 2573ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Shl8x8: size = 0; break; 2574ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Shl16x4: size = 1; break; 2575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Shl32x2: size = 2; break; 2576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: vassert(0); 2577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NShift(ARMneon_VSHL, 2579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, argR, size, False)); 2580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 2581ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2582ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QShl8x8: 2583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QShl16x4: 2584ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QShl32x2: 2585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QShl64x1: { 2586ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegD(env); 2587ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeon64Expr(env, e->Iex.Binop.arg1); 2588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeon64Expr(env, e->Iex.Binop.arg2); 2589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size; 2590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (e->Iex.Binop.op) { 2591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QShl8x8: size = 0; break; 2592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QShl16x4: size = 1; break; 2593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QShl32x2: size = 2; break; 2594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QShl64x1: size = 3; break; 2595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: vassert(0); 2596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NShift(ARMneon_VQSHL, 2598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, argR, size, False)); 2599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 2600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QSal8x8: 2602ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QSal16x4: 2603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QSal32x2: 2604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QSal64x1: { 2605ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegD(env); 2606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeon64Expr(env, e->Iex.Binop.arg1); 2607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeon64Expr(env, e->Iex.Binop.arg2); 2608ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size; 2609ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (e->Iex.Binop.op) { 2610ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QSal8x8: size = 0; break; 2611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QSal16x4: size = 1; break; 2612ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QSal32x2: size = 2; break; 2613ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QSal64x1: size = 3; break; 2614ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: vassert(0); 2615ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2616ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NShift(ARMneon_VQSAL, 2617ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, argR, size, False)); 2618ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 2619ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2620ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QShlN8x8: 2621ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QShlN16x4: 2622ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QShlN32x2: 2623ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QShlN64x1: { 2624ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegD(env); 2625ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeon64Expr(env, e->Iex.Binop.arg1); 2626ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size, imm; 2627ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->Iex.Binop.arg2->tag != Iex_Const || 2628ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown typeOfIRExpr(env->type_env, e->Iex.Binop.arg2) != Ity_I8) { 2629ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vpanic("ARM taget supports Iop_QShlNAxB with constant " 2630ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "second argument only\n"); 2631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown imm = e->Iex.Binop.arg2->Iex.Const.con->Ico.U8; 2633ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (e->Iex.Binop.op) { 2634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QShlN8x8: size = 8 | imm; break; 2635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QShlN16x4: size = 16 | imm; break; 2636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QShlN32x2: size = 32 | imm; break; 2637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QShlN64x1: size = 64 | imm; break; 2638ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: vassert(0); 2639ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2640ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnary(ARMneon_VQSHLNUU, 2641ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, size, False)); 2642ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 2643ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2644ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QShlN8Sx8: 2645ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QShlN16Sx4: 2646ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QShlN32Sx2: 2647ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QShlN64Sx1: { 2648ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegD(env); 2649ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeon64Expr(env, e->Iex.Binop.arg1); 2650ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size, imm; 2651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->Iex.Binop.arg2->tag != Iex_Const || 2652ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown typeOfIRExpr(env->type_env, e->Iex.Binop.arg2) != Ity_I8) { 2653ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vpanic("ARM taget supports Iop_QShlNAxB with constant " 2654ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "second argument only\n"); 2655ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2656ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown imm = e->Iex.Binop.arg2->Iex.Const.con->Ico.U8; 2657ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (e->Iex.Binop.op) { 2658ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QShlN8Sx8: size = 8 | imm; break; 2659ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QShlN16Sx4: size = 16 | imm; break; 2660ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QShlN32Sx2: size = 32 | imm; break; 2661ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QShlN64Sx1: size = 64 | imm; break; 2662ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: vassert(0); 2663ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2664ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnary(ARMneon_VQSHLNUS, 2665ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, size, False)); 2666ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 2667ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2668ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QSalN8x8: 2669ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QSalN16x4: 2670ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QSalN32x2: 2671ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QSalN64x1: { 2672ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegD(env); 2673ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeon64Expr(env, e->Iex.Binop.arg1); 2674ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size, imm; 2675ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->Iex.Binop.arg2->tag != Iex_Const || 2676ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown typeOfIRExpr(env->type_env, e->Iex.Binop.arg2) != Ity_I8) { 2677ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vpanic("ARM taget supports Iop_QShlNAxB with constant " 2678ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "second argument only\n"); 2679ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2680ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown imm = e->Iex.Binop.arg2->Iex.Const.con->Ico.U8; 2681ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (e->Iex.Binop.op) { 2682ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QSalN8x8: size = 8 | imm; break; 2683ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QSalN16x4: size = 16 | imm; break; 2684ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QSalN32x2: size = 32 | imm; break; 2685ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QSalN64x1: size = 64 | imm; break; 2686ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: vassert(0); 2687ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2688ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnary(ARMneon_VQSHLNSS, 2689ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, size, False)); 2690ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 2691ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2692ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_ShrN8x8: 2693ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_ShrN16x4: 2694ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_ShrN32x2: 2695ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Shr64: { 2696ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegD(env); 2697ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg tmp = newVRegD(env); 2698ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeon64Expr(env, e->Iex.Binop.arg1); 2699ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselIntExpr_R(env, e->Iex.Binop.arg2); 2700ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR2 = newVRegI(env); 2701ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size; 2702ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (e->Iex.Binop.op) { 2703ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_ShrN8x8: size = 0; break; 2704ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_ShrN16x4: size = 1; break; 2705ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_ShrN32x2: size = 2; break; 2706ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Shr64: size = 3; break; 2707ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: vassert(0); 2708ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2709ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_Unary(ARMun_NEG, argR2, argR)); 2710ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnary(ARMneon_DUP, tmp, argR2, 0, False)); 2711ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NShift(ARMneon_VSHL, 2712ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, tmp, size, False)); 2713ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 2714ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2715ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_ShlN8x8: 2716ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_ShlN16x4: 2717ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_ShlN32x2: 2718ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Shl64: { 2719ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegD(env); 2720ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg tmp = newVRegD(env); 2721ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeon64Expr(env, e->Iex.Binop.arg1); 2722ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselIntExpr_R(env, e->Iex.Binop.arg2); 2723ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size; 2724ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (e->Iex.Binop.op) { 2725ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_ShlN8x8: size = 0; break; 2726ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_ShlN16x4: size = 1; break; 2727ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_ShlN32x2: size = 2; break; 2728ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Shl64: size = 3; break; 2729ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: vassert(0); 2730ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2731ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnary(ARMneon_DUP, tmp, argR, 0, False)); 2732ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NShift(ARMneon_VSHL, 2733ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, tmp, size, False)); 2734ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 2735ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2736ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_SarN8x8: 2737ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_SarN16x4: 2738ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_SarN32x2: 2739ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Sar64: { 2740ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegD(env); 2741ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg tmp = newVRegD(env); 2742ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeon64Expr(env, e->Iex.Binop.arg1); 2743ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselIntExpr_R(env, e->Iex.Binop.arg2); 2744ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR2 = newVRegI(env); 2745ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size; 2746ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (e->Iex.Binop.op) { 2747ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_SarN8x8: size = 0; break; 2748ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_SarN16x4: size = 1; break; 2749ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_SarN32x2: size = 2; break; 2750ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Sar64: size = 3; break; 2751ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: vassert(0); 2752ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2753ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_Unary(ARMun_NEG, argR2, argR)); 2754ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnary(ARMneon_DUP, tmp, argR2, 0, False)); 2755ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NShift(ARMneon_VSAL, 2756ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, tmp, size, False)); 2757ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 2758ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2759ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CmpGT8Ux8: 2760ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CmpGT16Ux4: 2761ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CmpGT32Ux2: { 2762ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegD(env); 2763ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeon64Expr(env, e->Iex.Binop.arg1); 2764ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeon64Expr(env, e->Iex.Binop.arg2); 2765ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size; 2766ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (e->Iex.Binop.op) { 2767ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CmpGT8Ux8: size = 0; break; 2768ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CmpGT16Ux4: size = 1; break; 2769ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CmpGT32Ux2: size = 2; break; 2770ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: vassert(0); 2771ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2772ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NBinary(ARMneon_VCGTU, 2773ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, argR, size, False)); 2774ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 2775ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2776ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CmpGT8Sx8: 2777ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CmpGT16Sx4: 2778ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CmpGT32Sx2: { 2779ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegD(env); 2780ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeon64Expr(env, e->Iex.Binop.arg1); 2781ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeon64Expr(env, e->Iex.Binop.arg2); 2782ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size; 2783ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (e->Iex.Binop.op) { 2784ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CmpGT8Sx8: size = 0; break; 2785ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CmpGT16Sx4: size = 1; break; 2786ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CmpGT32Sx2: size = 2; break; 2787ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: vassert(0); 2788ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2789ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NBinary(ARMneon_VCGTS, 2790ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, argR, size, False)); 2791ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 2792ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2793ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CmpEQ8x8: 2794ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CmpEQ16x4: 2795ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CmpEQ32x2: { 2796ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegD(env); 2797ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeon64Expr(env, e->Iex.Binop.arg1); 2798ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeon64Expr(env, e->Iex.Binop.arg2); 2799ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size; 2800ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (e->Iex.Binop.op) { 2801ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CmpEQ8x8: size = 0; break; 2802ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CmpEQ16x4: size = 1; break; 2803ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CmpEQ32x2: size = 2; break; 2804ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: vassert(0); 2805ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2806ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NBinary(ARMneon_VCEQ, 2807ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, argR, size, False)); 2808ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 2809ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2810ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Mul8x8: 2811ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Mul16x4: 2812ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Mul32x2: { 2813ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegD(env); 2814ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeon64Expr(env, e->Iex.Binop.arg1); 2815ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeon64Expr(env, e->Iex.Binop.arg2); 2816ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size = 0; 2817ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch(e->Iex.Binop.op) { 2818ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Mul8x8: size = 0; break; 2819ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Mul16x4: size = 1; break; 2820ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Mul32x2: size = 2; break; 2821ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: vassert(0); 2822ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2823ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NBinary(ARMneon_VMUL, 2824ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, argR, size, False)); 2825ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 2826ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2827ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Mul32Fx2: { 2828ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegD(env); 2829ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeon64Expr(env, e->Iex.Binop.arg1); 2830ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeon64Expr(env, e->Iex.Binop.arg2); 2831ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size = 0; 2832ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NBinary(ARMneon_VMULFP, 2833ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, argR, size, False)); 2834ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 2835ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2836ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QDMulHi16Sx4: 2837ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QDMulHi32Sx2: { 2838ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegD(env); 2839ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeon64Expr(env, e->Iex.Binop.arg1); 2840ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeon64Expr(env, e->Iex.Binop.arg2); 2841ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size = 0; 2842ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch(e->Iex.Binop.op) { 2843ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QDMulHi16Sx4: size = 1; break; 2844ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QDMulHi32Sx2: size = 2; break; 2845ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: vassert(0); 2846ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2847ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NBinary(ARMneon_VQDMULH, 2848ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, argR, size, False)); 2849ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 2850ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2851ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2852ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QRDMulHi16Sx4: 2853ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QRDMulHi32Sx2: { 2854ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegD(env); 2855ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeon64Expr(env, e->Iex.Binop.arg1); 2856ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeon64Expr(env, e->Iex.Binop.arg2); 2857ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size = 0; 2858ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch(e->Iex.Binop.op) { 2859ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QRDMulHi16Sx4: size = 1; break; 2860ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QRDMulHi32Sx2: size = 2; break; 2861ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: vassert(0); 2862ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2863ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NBinary(ARMneon_VQRDMULH, 2864ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, argR, size, False)); 2865ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 2866ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2867ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2868ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_PwAdd8x8: 2869ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_PwAdd16x4: 2870ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_PwAdd32x2: { 2871ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegD(env); 2872ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeon64Expr(env, e->Iex.Binop.arg1); 2873ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeon64Expr(env, e->Iex.Binop.arg2); 2874ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size = 0; 2875ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch(e->Iex.Binop.op) { 2876ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_PwAdd8x8: size = 0; break; 2877ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_PwAdd16x4: size = 1; break; 2878ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_PwAdd32x2: size = 2; break; 2879ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: vassert(0); 2880ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2881ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NBinary(ARMneon_VPADD, 2882ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, argR, size, False)); 2883ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 2884ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2885ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_PwAdd32Fx2: { 2886ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegD(env); 2887ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeon64Expr(env, e->Iex.Binop.arg1); 2888ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeon64Expr(env, e->Iex.Binop.arg2); 2889ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size = 0; 2890ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NBinary(ARMneon_VPADDFP, 2891ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, argR, size, False)); 2892ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 2893ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2894ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_PwMin8Ux8: 2895ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_PwMin16Ux4: 2896ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_PwMin32Ux2: { 2897ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegD(env); 2898ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeon64Expr(env, e->Iex.Binop.arg1); 2899ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeon64Expr(env, e->Iex.Binop.arg2); 2900ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size = 0; 2901ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch(e->Iex.Binop.op) { 2902ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_PwMin8Ux8: size = 0; break; 2903ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_PwMin16Ux4: size = 1; break; 2904ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_PwMin32Ux2: size = 2; break; 2905ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: vassert(0); 2906ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2907ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NBinary(ARMneon_VPMINU, 2908ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, argR, size, False)); 2909ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 2910ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2911ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_PwMin8Sx8: 2912ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_PwMin16Sx4: 2913ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_PwMin32Sx2: { 2914ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegD(env); 2915ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeon64Expr(env, e->Iex.Binop.arg1); 2916ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeon64Expr(env, e->Iex.Binop.arg2); 2917ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size = 0; 2918ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch(e->Iex.Binop.op) { 2919ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_PwMin8Sx8: size = 0; break; 2920ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_PwMin16Sx4: size = 1; break; 2921ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_PwMin32Sx2: size = 2; break; 2922ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: vassert(0); 2923ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2924ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NBinary(ARMneon_VPMINS, 2925ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, argR, size, False)); 2926ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 2927ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2928ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_PwMax8Ux8: 2929ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_PwMax16Ux4: 2930ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_PwMax32Ux2: { 2931ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegD(env); 2932ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeon64Expr(env, e->Iex.Binop.arg1); 2933ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeon64Expr(env, e->Iex.Binop.arg2); 2934ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size = 0; 2935ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch(e->Iex.Binop.op) { 2936ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_PwMax8Ux8: size = 0; break; 2937ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_PwMax16Ux4: size = 1; break; 2938ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_PwMax32Ux2: size = 2; break; 2939ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: vassert(0); 2940ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2941ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NBinary(ARMneon_VPMAXU, 2942ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, argR, size, False)); 2943ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 2944ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2945ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_PwMax8Sx8: 2946ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_PwMax16Sx4: 2947ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_PwMax32Sx2: { 2948ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegD(env); 2949ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeon64Expr(env, e->Iex.Binop.arg1); 2950ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeon64Expr(env, e->Iex.Binop.arg2); 2951ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size = 0; 2952ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch(e->Iex.Binop.op) { 2953ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_PwMax8Sx8: size = 0; break; 2954ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_PwMax16Sx4: size = 1; break; 2955ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_PwMax32Sx2: size = 2; break; 2956ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: vassert(0); 2957ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2958ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NBinary(ARMneon_VPMAXS, 2959ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, argR, size, False)); 2960ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 2961ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2962ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Perm8x8: { 2963ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegD(env); 2964ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeon64Expr(env, e->Iex.Binop.arg1); 2965ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeon64Expr(env, e->Iex.Binop.arg2); 2966ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NBinary(ARMneon_VTBL, 2967ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, argR, 0, False)); 2968ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 2969ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2970ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_PolynomialMul8x8: { 2971ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegD(env); 2972ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeon64Expr(env, e->Iex.Binop.arg1); 2973ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeon64Expr(env, e->Iex.Binop.arg2); 2974ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size = 0; 2975ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NBinary(ARMneon_VMULP, 2976ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, argR, size, False)); 2977ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 2978ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2979ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Max32Fx2: { 2980ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegD(env); 2981ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeon64Expr(env, e->Iex.Binop.arg1); 2982ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeon64Expr(env, e->Iex.Binop.arg2); 2983ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NBinary(ARMneon_VMAXF, 2984ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, argR, 2, False)); 2985ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 2986ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2987ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Min32Fx2: { 2988ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegD(env); 2989ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeon64Expr(env, e->Iex.Binop.arg1); 2990ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeon64Expr(env, e->Iex.Binop.arg2); 2991ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NBinary(ARMneon_VMINF, 2992ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, argR, 2, False)); 2993ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 2994ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2995ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_PwMax32Fx2: { 2996ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegD(env); 2997ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeon64Expr(env, e->Iex.Binop.arg1); 2998ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeon64Expr(env, e->Iex.Binop.arg2); 2999ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NBinary(ARMneon_VPMAXF, 3000ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, argR, 2, False)); 3001ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 3002ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3003ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_PwMin32Fx2: { 3004ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegD(env); 3005ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeon64Expr(env, e->Iex.Binop.arg1); 3006ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeon64Expr(env, e->Iex.Binop.arg2); 3007ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NBinary(ARMneon_VPMINF, 3008ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, argR, 2, False)); 3009ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 3010ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3011ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CmpGT32Fx2: { 3012ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegD(env); 3013ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeon64Expr(env, e->Iex.Binop.arg1); 3014ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeon64Expr(env, e->Iex.Binop.arg2); 3015ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NBinary(ARMneon_VCGTF, 3016ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, argR, 2, False)); 3017ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 3018ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3019ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CmpGE32Fx2: { 3020ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegD(env); 3021ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeon64Expr(env, e->Iex.Binop.arg1); 3022ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeon64Expr(env, e->Iex.Binop.arg2); 3023ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NBinary(ARMneon_VCGEF, 3024ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, argR, 2, False)); 3025ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 3026ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3027ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CmpEQ32Fx2: { 3028ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegD(env); 3029ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeon64Expr(env, e->Iex.Binop.arg1); 3030ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeon64Expr(env, e->Iex.Binop.arg2); 3031ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NBinary(ARMneon_VCEQF, 3032ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, argR, 2, False)); 3033ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 3034ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3035ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_F32ToFixed32Ux2_RZ: 3036ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_F32ToFixed32Sx2_RZ: 3037ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Fixed32UToF32x2_RN: 3038ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Fixed32SToF32x2_RN: { 3039ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegD(env); 3040ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg arg = iselNeon64Expr(env, e->Iex.Binop.arg1); 3041ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ARMNeonUnOp op; 3042ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt imm6; 3043ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->Iex.Binop.arg2->tag != Iex_Const || 3044ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown typeOfIRExpr(env->type_env, e->Iex.Binop.arg2) != Ity_I8) { 3045ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vpanic("ARM supports FP <-> Fixed conversion with constant " 3046ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "second argument less than 33 only\n"); 3047ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3048ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown imm6 = e->Iex.Binop.arg2->Iex.Const.con->Ico.U8; 3049ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert(imm6 <= 32 && imm6 > 0); 3050ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown imm6 = 64 - imm6; 3051ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch(e->Iex.Binop.op) { 3052ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_F32ToFixed32Ux2_RZ: op = ARMneon_VCVTFtoFixedU; break; 3053ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_F32ToFixed32Sx2_RZ: op = ARMneon_VCVTFtoFixedS; break; 3054ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Fixed32UToF32x2_RN: op = ARMneon_VCVTFixedUtoF; break; 3055ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Fixed32SToF32x2_RN: op = ARMneon_VCVTFixedStoF; break; 3056ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: vassert(0); 3057ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3058ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnary(op, res, arg, imm6, False)); 3059ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 3060ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3061ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* 3062ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown FIXME: is this here or not? 3063ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_VDup8x8: 3064ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_VDup16x4: 3065ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_VDup32x2: { 3066ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegD(env); 3067ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeon64Expr(env, e->Iex.Binop.arg1); 3068ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt index; 3069ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt imm4; 3070ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size = 0; 3071ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->Iex.Binop.arg2->tag != Iex_Const || 3072ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown typeOfIRExpr(env->type_env, e->Iex.Binop.arg2) != Ity_I8) { 3073ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vpanic("ARM supports Iop_VDup with constant " 3074ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "second argument less than 16 only\n"); 3075ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3076ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown index = e->Iex.Binop.arg2->Iex.Const.con->Ico.U8; 3077ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch(e->Iex.Binop.op) { 3078ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_VDup8x8: imm4 = (index << 1) + 1; break; 3079ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_VDup16x4: imm4 = (index << 2) + 2; break; 3080ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_VDup32x2: imm4 = (index << 3) + 4; break; 3081ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: vassert(0); 3082ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3083ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (imm4 >= 16) { 3084ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vpanic("ARM supports Iop_VDup with constant " 3085ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "second argument less than 16 only\n"); 3086ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3087ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnary(ARMneon_VDUP, 3088ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, imm4, False)); 3089ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 3090ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3091ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */ 3092ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: 3093ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 3094ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3095ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3096ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3097ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* --------- UNARY ops --------- */ 3098ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->tag == Iex_Unop) { 3099ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (e->Iex.Unop.op) { 3100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* ReinterpF64asI64 */ 3102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_ReinterpF64asI64: 3103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Left64(e) */ 3104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Left64: 3105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* CmpwNEZ64(e) */ 3106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown //case Iop_CmpwNEZ64: 3107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_1Sto64: { 3108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg rLo, rHi; 3109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegD(env); 3110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown iselInt64Expr(&rHi, &rLo, env, e); 3111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_VXferD(True/*toD*/, res, rHi, rLo)); 3112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 3113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Not64: { 3115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DECLARE_PATTERN(p_veqz_8x8); 3116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DECLARE_PATTERN(p_veqz_16x4); 3117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DECLARE_PATTERN(p_veqz_32x2); 3118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DECLARE_PATTERN(p_vcge_8sx8); 3119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DECLARE_PATTERN(p_vcge_16sx4); 3120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DECLARE_PATTERN(p_vcge_32sx2); 3121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DECLARE_PATTERN(p_vcge_8ux8); 3122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DECLARE_PATTERN(p_vcge_16ux4); 3123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DECLARE_PATTERN(p_vcge_32ux2); 3124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEFINE_PATTERN(p_veqz_8x8, 3125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown unop(Iop_Not64, unop(Iop_CmpNEZ8x8, bind(0)))); 3126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEFINE_PATTERN(p_veqz_16x4, 3127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown unop(Iop_Not64, unop(Iop_CmpNEZ16x4, bind(0)))); 3128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEFINE_PATTERN(p_veqz_32x2, 3129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown unop(Iop_Not64, unop(Iop_CmpNEZ32x2, bind(0)))); 3130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEFINE_PATTERN(p_vcge_8sx8, 3131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown unop(Iop_Not64, binop(Iop_CmpGT8Sx8, bind(1), bind(0)))); 3132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEFINE_PATTERN(p_vcge_16sx4, 3133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown unop(Iop_Not64, binop(Iop_CmpGT16Sx4, bind(1), bind(0)))); 3134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEFINE_PATTERN(p_vcge_32sx2, 3135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown unop(Iop_Not64, binop(Iop_CmpGT32Sx2, bind(1), bind(0)))); 3136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEFINE_PATTERN(p_vcge_8ux8, 3137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown unop(Iop_Not64, binop(Iop_CmpGT8Ux8, bind(1), bind(0)))); 3138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEFINE_PATTERN(p_vcge_16ux4, 3139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown unop(Iop_Not64, binop(Iop_CmpGT16Ux4, bind(1), bind(0)))); 3140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEFINE_PATTERN(p_vcge_32ux2, 3141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown unop(Iop_Not64, binop(Iop_CmpGT32Ux2, bind(1), bind(0)))); 3142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (matchIRExpr(&mi, p_veqz_8x8, e)) { 3143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegD(env); 3144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg arg = iselNeon64Expr(env, mi.bindee[0]); 3145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnary(ARMneon_EQZ, res, arg, 0, False)); 3146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 3147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else if (matchIRExpr(&mi, p_veqz_16x4, e)) { 3148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegD(env); 3149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg arg = iselNeon64Expr(env, mi.bindee[0]); 3150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnary(ARMneon_EQZ, res, arg, 1, False)); 3151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 3152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else if (matchIRExpr(&mi, p_veqz_32x2, e)) { 3153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegD(env); 3154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg arg = iselNeon64Expr(env, mi.bindee[0]); 3155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnary(ARMneon_EQZ, res, arg, 2, False)); 3156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 3157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else if (matchIRExpr(&mi, p_vcge_8sx8, e)) { 3158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegD(env); 3159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeon64Expr(env, mi.bindee[0]); 3160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeon64Expr(env, mi.bindee[1]); 3161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NBinary(ARMneon_VCGES, 3162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, argR, 0, False)); 3163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 3164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else if (matchIRExpr(&mi, p_vcge_16sx4, e)) { 3165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegD(env); 3166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeon64Expr(env, mi.bindee[0]); 3167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeon64Expr(env, mi.bindee[1]); 3168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NBinary(ARMneon_VCGES, 3169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, argR, 1, False)); 3170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 3171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else if (matchIRExpr(&mi, p_vcge_32sx2, e)) { 3172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegD(env); 3173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeon64Expr(env, mi.bindee[0]); 3174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeon64Expr(env, mi.bindee[1]); 3175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NBinary(ARMneon_VCGES, 3176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, argR, 2, False)); 3177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 3178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else if (matchIRExpr(&mi, p_vcge_8ux8, e)) { 3179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegD(env); 3180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeon64Expr(env, mi.bindee[0]); 3181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeon64Expr(env, mi.bindee[1]); 3182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NBinary(ARMneon_VCGEU, 3183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, argR, 0, False)); 3184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 3185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else if (matchIRExpr(&mi, p_vcge_16ux4, e)) { 3186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegD(env); 3187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeon64Expr(env, mi.bindee[0]); 3188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeon64Expr(env, mi.bindee[1]); 3189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NBinary(ARMneon_VCGEU, 3190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, argR, 1, False)); 3191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 3192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else if (matchIRExpr(&mi, p_vcge_32ux2, e)) { 3193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegD(env); 3194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeon64Expr(env, mi.bindee[0]); 3195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeon64Expr(env, mi.bindee[1]); 3196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NBinary(ARMneon_VCGEU, 3197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, argR, 2, False)); 3198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 3199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 3200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegD(env); 3201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg arg = iselNeon64Expr(env, e->Iex.Unop.arg); 3202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnary(ARMneon_NOT, res, arg, 4, False)); 3203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 3204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Dup8x8: 3207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Dup16x4: 3208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Dup32x2: { 3209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res, arg; 3210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size; 3211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DECLARE_PATTERN(p_vdup_8x8); 3212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DECLARE_PATTERN(p_vdup_16x4); 3213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DECLARE_PATTERN(p_vdup_32x2); 3214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEFINE_PATTERN(p_vdup_8x8, 3215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown unop(Iop_Dup8x8, binop(Iop_GetElem8x8, bind(0), bind(1)))); 3216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEFINE_PATTERN(p_vdup_16x4, 3217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown unop(Iop_Dup16x4, binop(Iop_GetElem16x4, bind(0), bind(1)))); 3218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEFINE_PATTERN(p_vdup_32x2, 3219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown unop(Iop_Dup32x2, binop(Iop_GetElem32x2, bind(0), bind(1)))); 3220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (matchIRExpr(&mi, p_vdup_8x8, e)) { 3221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt index; 3222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt imm4; 3223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (mi.bindee[1]->tag == Iex_Const && 3224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown typeOfIRExpr(env->type_env, mi.bindee[1]) == Ity_I8) { 3225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown index = mi.bindee[1]->Iex.Const.con->Ico.U8; 3226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown imm4 = (index << 1) + 1; 3227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (index < 8) { 3228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res = newVRegD(env); 3229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown arg = iselNeon64Expr(env, mi.bindee[0]); 3230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnaryS( 3231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ARMneon_VDUP, 3232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mkARMNRS(ARMNRS_Reg, res, 0), 3233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mkARMNRS(ARMNRS_Scalar, arg, index), 3234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown imm4, False 3235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown )); 3236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 3237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else if (matchIRExpr(&mi, p_vdup_16x4, e)) { 3240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt index; 3241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt imm4; 3242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (mi.bindee[1]->tag == Iex_Const && 3243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown typeOfIRExpr(env->type_env, mi.bindee[1]) == Ity_I8) { 3244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown index = mi.bindee[1]->Iex.Const.con->Ico.U8; 3245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown imm4 = (index << 2) + 2; 3246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (index < 4) { 3247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res = newVRegD(env); 3248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown arg = iselNeon64Expr(env, mi.bindee[0]); 3249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnaryS( 3250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ARMneon_VDUP, 3251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mkARMNRS(ARMNRS_Reg, res, 0), 3252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mkARMNRS(ARMNRS_Scalar, arg, index), 3253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown imm4, False 3254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown )); 3255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 3256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else if (matchIRExpr(&mi, p_vdup_32x2, e)) { 3259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt index; 3260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt imm4; 3261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (mi.bindee[1]->tag == Iex_Const && 3262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown typeOfIRExpr(env->type_env, mi.bindee[1]) == Ity_I8) { 3263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown index = mi.bindee[1]->Iex.Const.con->Ico.U8; 3264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown imm4 = (index << 3) + 4; 3265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (index < 2) { 3266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res = newVRegD(env); 3267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown arg = iselNeon64Expr(env, mi.bindee[0]); 3268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnaryS( 3269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ARMneon_VDUP, 3270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mkARMNRS(ARMNRS_Reg, res, 0), 3271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mkARMNRS(ARMNRS_Scalar, arg, index), 3272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown imm4, False 3273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown )); 3274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 3275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown arg = iselIntExpr_R(env, e->Iex.Unop.arg); 3279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res = newVRegD(env); 3280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (e->Iex.Unop.op) { 3281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Dup8x8: size = 0; break; 3282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Dup16x4: size = 1; break; 3283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Dup32x2: size = 2; break; 3284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: vassert(0); 3285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnary(ARMneon_DUP, res, arg, size, False)); 3287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 3288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Abs8x8: 3290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Abs16x4: 3291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Abs32x2: { 3292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegD(env); 3293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg arg = iselNeon64Expr(env, e->Iex.Unop.arg); 3294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size = 0; 3295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch(e->Iex.Binop.op) { 3296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Abs8x8: size = 0; break; 3297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Abs16x4: size = 1; break; 3298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Abs32x2: size = 2; break; 3299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: vassert(0); 3300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnary(ARMneon_ABS, res, arg, size, False)); 3302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 3303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Reverse64_8x8: 3305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Reverse64_16x4: 3306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Reverse64_32x2: { 3307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegD(env); 3308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg arg = iselNeon64Expr(env, e->Iex.Unop.arg); 3309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size = 0; 3310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch(e->Iex.Binop.op) { 3311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Reverse64_8x8: size = 0; break; 3312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Reverse64_16x4: size = 1; break; 3313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Reverse64_32x2: size = 2; break; 3314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: vassert(0); 3315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnary(ARMneon_REV64, 3317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, arg, size, False)); 3318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 3319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Reverse32_8x8: 3321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Reverse32_16x4: { 3322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegD(env); 3323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg arg = iselNeon64Expr(env, e->Iex.Unop.arg); 3324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size = 0; 3325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch(e->Iex.Binop.op) { 3326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Reverse32_8x8: size = 0; break; 3327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Reverse32_16x4: size = 1; break; 3328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: vassert(0); 3329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnary(ARMneon_REV32, 3331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, arg, size, False)); 3332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 3333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Reverse16_8x8: { 3335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegD(env); 3336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg arg = iselNeon64Expr(env, e->Iex.Unop.arg); 3337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size = 0; 3338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnary(ARMneon_REV16, 3339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, arg, size, False)); 3340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 3341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CmpwNEZ64: { 3343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg x_lsh = newVRegD(env); 3344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg x_rsh = newVRegD(env); 3345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg lsh_amt = newVRegD(env); 3346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg rsh_amt = newVRegD(env); 3347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg zero = newVRegD(env); 3348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg tmp = newVRegD(env); 3349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg tmp2 = newVRegD(env); 3350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegD(env); 3351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg x = newVRegD(env); 3352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg arg = iselNeon64Expr(env, e->Iex.Unop.arg); 3353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnary(ARMneon_EQZ, tmp2, arg, 2, False)); 3354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnary(ARMneon_NOT, x, tmp2, 4, False)); 3355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NeonImm(lsh_amt, ARMNImm_TI(0, 32))); 3356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NeonImm(zero, ARMNImm_TI(0, 0))); 3357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NBinary(ARMneon_VSUB, 3358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown rsh_amt, zero, lsh_amt, 2, False)); 3359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NShift(ARMneon_VSHL, 3360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown x_lsh, x, lsh_amt, 3, False)); 3361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NShift(ARMneon_VSHL, 3362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown x_rsh, x, rsh_amt, 3, False)); 3363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NBinary(ARMneon_VORR, 3364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tmp, x_lsh, x_rsh, 0, False)); 3365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NBinary(ARMneon_VORR, 3366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, tmp, x, 0, False)); 3367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 3368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CmpNEZ8x8: 3370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CmpNEZ16x4: 3371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CmpNEZ32x2: { 3372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegD(env); 3373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg tmp = newVRegD(env); 3374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg arg = iselNeon64Expr(env, e->Iex.Unop.arg); 3375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size; 3376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (e->Iex.Unop.op) { 3377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CmpNEZ8x8: size = 0; break; 3378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CmpNEZ16x4: size = 1; break; 3379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CmpNEZ32x2: size = 2; break; 3380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: vassert(0); 3381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnary(ARMneon_EQZ, tmp, arg, size, False)); 3383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnary(ARMneon_NOT, res, tmp, 4, False)); 3384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 3385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3386b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov case Iop_NarrowUn16to8x8: 3387b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov case Iop_NarrowUn32to16x4: 3388b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov case Iop_NarrowUn64to32x2: { 3389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegD(env); 3390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg arg = iselNeonExpr(env, e->Iex.Unop.arg); 3391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size = 0; 3392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch(e->Iex.Binop.op) { 3393b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov case Iop_NarrowUn16to8x8: size = 0; break; 3394b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov case Iop_NarrowUn32to16x4: size = 1; break; 3395b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov case Iop_NarrowUn64to32x2: size = 2; break; 3396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: vassert(0); 3397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnary(ARMneon_COPYN, 3399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, arg, size, False)); 3400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 3401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3402b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov case Iop_QNarrowUn16Sto8Sx8: 3403b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov case Iop_QNarrowUn32Sto16Sx4: 3404b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov case Iop_QNarrowUn64Sto32Sx2: { 3405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegD(env); 3406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg arg = iselNeonExpr(env, e->Iex.Unop.arg); 3407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size = 0; 3408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch(e->Iex.Binop.op) { 3409b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov case Iop_QNarrowUn16Sto8Sx8: size = 0; break; 3410b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov case Iop_QNarrowUn32Sto16Sx4: size = 1; break; 3411b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov case Iop_QNarrowUn64Sto32Sx2: size = 2; break; 3412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: vassert(0); 3413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnary(ARMneon_COPYQNSS, 3415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, arg, size, False)); 3416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 3417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3418b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov case Iop_QNarrowUn16Sto8Ux8: 3419b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov case Iop_QNarrowUn32Sto16Ux4: 3420b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov case Iop_QNarrowUn64Sto32Ux2: { 3421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegD(env); 3422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg arg = iselNeonExpr(env, e->Iex.Unop.arg); 3423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size = 0; 3424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch(e->Iex.Binop.op) { 3425b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov case Iop_QNarrowUn16Sto8Ux8: size = 0; break; 3426b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov case Iop_QNarrowUn32Sto16Ux4: size = 1; break; 3427b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov case Iop_QNarrowUn64Sto32Ux2: size = 2; break; 3428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: vassert(0); 3429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnary(ARMneon_COPYQNUS, 3431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, arg, size, False)); 3432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 3433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3434b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov case Iop_QNarrowUn16Uto8Ux8: 3435b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov case Iop_QNarrowUn32Uto16Ux4: 3436b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov case Iop_QNarrowUn64Uto32Ux2: { 3437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegD(env); 3438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg arg = iselNeonExpr(env, e->Iex.Unop.arg); 3439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size = 0; 3440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch(e->Iex.Binop.op) { 3441b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov case Iop_QNarrowUn16Uto8Ux8: size = 0; break; 3442b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov case Iop_QNarrowUn32Uto16Ux4: size = 1; break; 3443b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov case Iop_QNarrowUn64Uto32Ux2: size = 2; break; 3444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: vassert(0); 3445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnary(ARMneon_COPYQNUU, 3447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, arg, size, False)); 3448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 3449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_PwAddL8Sx8: 3451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_PwAddL16Sx4: 3452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_PwAddL32Sx2: { 3453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegD(env); 3454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg arg = iselNeon64Expr(env, e->Iex.Unop.arg); 3455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size = 0; 3456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch(e->Iex.Binop.op) { 3457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_PwAddL8Sx8: size = 0; break; 3458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_PwAddL16Sx4: size = 1; break; 3459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_PwAddL32Sx2: size = 2; break; 3460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: vassert(0); 3461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnary(ARMneon_PADDLS, 3463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, arg, size, False)); 3464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 3465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_PwAddL8Ux8: 3467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_PwAddL16Ux4: 3468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_PwAddL32Ux2: { 3469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegD(env); 3470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg arg = iselNeon64Expr(env, e->Iex.Unop.arg); 3471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size = 0; 3472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch(e->Iex.Binop.op) { 3473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_PwAddL8Ux8: size = 0; break; 3474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_PwAddL16Ux4: size = 1; break; 3475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_PwAddL32Ux2: size = 2; break; 3476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: vassert(0); 3477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnary(ARMneon_PADDLU, 3479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, arg, size, False)); 3480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 3481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Cnt8x8: { 3483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegD(env); 3484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg arg = iselNeon64Expr(env, e->Iex.Unop.arg); 3485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size = 0; 3486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnary(ARMneon_CNT, 3487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, arg, size, False)); 3488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 3489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Clz8Sx8: 3491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Clz16Sx4: 3492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Clz32Sx2: { 3493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegD(env); 3494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg arg = iselNeon64Expr(env, e->Iex.Unop.arg); 3495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size = 0; 3496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch(e->Iex.Binop.op) { 3497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Clz8Sx8: size = 0; break; 3498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Clz16Sx4: size = 1; break; 3499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Clz32Sx2: size = 2; break; 3500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: vassert(0); 3501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnary(ARMneon_CLZ, 3503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, arg, size, False)); 3504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 3505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3506ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Cls8Sx8: 3507ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Cls16Sx4: 3508ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Cls32Sx2: { 3509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegD(env); 3510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg arg = iselNeon64Expr(env, e->Iex.Unop.arg); 3511ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size = 0; 3512ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch(e->Iex.Binop.op) { 3513ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Cls8Sx8: size = 0; break; 3514ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Cls16Sx4: size = 1; break; 3515ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Cls32Sx2: size = 2; break; 3516ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: vassert(0); 3517ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnary(ARMneon_CLS, 3519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, arg, size, False)); 3520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 3521ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_FtoI32Sx2_RZ: { 3523ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegD(env); 3524ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg arg = iselNeon64Expr(env, e->Iex.Unop.arg); 3525ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnary(ARMneon_VCVTFtoS, 3526ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, arg, 2, False)); 3527ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 3528ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3529ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_FtoI32Ux2_RZ: { 3530ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegD(env); 3531ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg arg = iselNeon64Expr(env, e->Iex.Unop.arg); 3532ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnary(ARMneon_VCVTFtoU, 3533ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, arg, 2, False)); 3534ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 3535ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3536ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_I32StoFx2: { 3537ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegD(env); 3538ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg arg = iselNeon64Expr(env, e->Iex.Unop.arg); 3539ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnary(ARMneon_VCVTStoF, 3540ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, arg, 2, False)); 3541ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 3542ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3543ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_I32UtoFx2: { 3544ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegD(env); 3545ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg arg = iselNeon64Expr(env, e->Iex.Unop.arg); 3546ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnary(ARMneon_VCVTUtoF, 3547ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, arg, 2, False)); 3548ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 3549ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3550ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_F32toF16x4: { 3551ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegD(env); 3552ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg arg = iselNeonExpr(env, e->Iex.Unop.arg); 3553ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnary(ARMneon_VCVTF32toF16, 3554ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, arg, 2, False)); 3555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 3556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Recip32Fx2: { 3558ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegD(env); 3559ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeon64Expr(env, e->Iex.Binop.arg1); 3560ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnary(ARMneon_VRECIPF, 3561ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, 0, False)); 3562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 3563ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3564ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Recip32x2: { 3565ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegD(env); 3566ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeon64Expr(env, e->Iex.Binop.arg1); 3567ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnary(ARMneon_VRECIP, 3568ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, 0, False)); 3569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 3570ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3571ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Abs32Fx2: { 3572ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DECLARE_PATTERN(p_vabd_32fx2); 3573ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEFINE_PATTERN(p_vabd_32fx2, 3574ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown unop(Iop_Abs32Fx2, 3575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown binop(Iop_Sub32Fx2, 3576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown bind(0), 3577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown bind(1)))); 3578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (matchIRExpr(&mi, p_vabd_32fx2, e)) { 3579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegD(env); 3580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeon64Expr(env, mi.bindee[0]); 3581ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeon64Expr(env, mi.bindee[1]); 3582ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NBinary(ARMneon_VABDFP, 3583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, argR, 0, False)); 3584ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 3585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 3586ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegD(env); 3587ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg arg = iselNeon64Expr(env, e->Iex.Unop.arg); 3588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnary(ARMneon_VABSFP, 3589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, arg, 0, False)); 3590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 3591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Rsqrte32Fx2: { 3594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegD(env); 3595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg arg = iselNeon64Expr(env, e->Iex.Unop.arg); 3596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnary(ARMneon_VRSQRTEFP, 3597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, arg, 0, False)); 3598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 3599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Rsqrte32x2: { 3601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegD(env); 3602ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg arg = iselNeon64Expr(env, e->Iex.Unop.arg); 3603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnary(ARMneon_VRSQRTE, 3604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, arg, 0, False)); 3605ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 3606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Neg32Fx2: { 3608ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegD(env); 3609ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg arg = iselNeon64Expr(env, e->Iex.Unop.arg); 3610ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnary(ARMneon_VNEGF, 3611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, arg, 0, False)); 3612ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 3613ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3614ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: 3615ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 3616ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3617ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } /* if (e->tag == Iex_Unop) */ 3618ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3619ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->tag == Iex_Triop) { 3620663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng IRTriop *triop = e->Iex.Triop.details; 3621663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 3622663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng switch (triop->op) { 3623ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Extract64: { 3624ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegD(env); 3625663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng HReg argL = iselNeon64Expr(env, triop->arg1); 3626663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng HReg argR = iselNeon64Expr(env, triop->arg2); 3627ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt imm4; 3628663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng if (triop->arg3->tag != Iex_Const || 3629663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng typeOfIRExpr(env->type_env, triop->arg3) != Ity_I8) { 3630ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vpanic("ARM target supports Iop_Extract64 with constant " 3631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "third argument less than 16 only\n"); 3632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3633663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng imm4 = triop->arg3->Iex.Const.con->Ico.U8; 3634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (imm4 >= 8) { 3635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vpanic("ARM target supports Iop_Extract64 with constant " 3636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "third argument less than 16 only\n"); 3637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3638ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NBinary(ARMneon_VEXT, 3639ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, argR, imm4, False)); 3640ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 3641ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3642ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_SetElem8x8: 3643ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_SetElem16x4: 3644ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_SetElem32x2: { 3645ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegD(env); 3646663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng HReg dreg = iselNeon64Expr(env, triop->arg1); 3647663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng HReg arg = iselIntExpr_R(env, triop->arg3); 3648ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt index, size; 3649663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng if (triop->arg2->tag != Iex_Const || 3650663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng typeOfIRExpr(env->type_env, triop->arg2) != Ity_I8) { 3651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vpanic("ARM target supports SetElem with constant " 3652ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "second argument only\n"); 3653ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3654663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng index = triop->arg2->Iex.Const.con->Ico.U8; 3655663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng switch (triop->op) { 3656ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_SetElem8x8: vassert(index < 8); size = 0; break; 3657ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_SetElem16x4: vassert(index < 4); size = 1; break; 3658ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_SetElem32x2: vassert(index < 2); size = 2; break; 3659ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: vassert(0); 3660ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3661ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnary(ARMneon_COPY, res, dreg, 4, False)); 3662ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnaryS(ARMneon_SETELEM, 3663ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mkARMNRS(ARMNRS_Scalar, res, index), 3664ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mkARMNRS(ARMNRS_Reg, arg, 0), 3665ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown size, False)); 3666ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 3667ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3668ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: 3669ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 3670ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3671ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3672ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3673ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* --------- MULTIPLEX --------- */ 3674ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->tag == Iex_Mux0X) { 3675ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg rLo, rHi; 3676ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegD(env); 3677ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown iselInt64Expr(&rHi, &rLo, env, e); 3678ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_VXferD(True/*toD*/, res, rHi, rLo)); 3679ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 3680ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3681ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3682ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ppIRExpr(e); 3683ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vpanic("iselNeon64Expr"); 3684ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 3685ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3686ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic HReg iselNeonExpr ( ISelEnv* env, IRExpr* e ) 3687ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 3688ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg r = iselNeonExpr_wrk( env, e ); 3689ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert(hregClass(r) == HRcVec128); 3690ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert(hregIsVirtual(r)); 3691ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return r; 3692ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 3693ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3694ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* DO NOT CALL THIS DIRECTLY */ 3695ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic HReg iselNeonExpr_wrk ( ISelEnv* env, IRExpr* e ) 3696ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 3697ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRType ty = typeOfIRExpr(env->type_env, e); 3698ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown MatchInfo mi; 3699ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert(e); 3700ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert(ty == Ity_V128); 3701ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3702ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->tag == Iex_RdTmp) { 3703ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return lookupIRTemp(env, e->Iex.RdTmp.tmp); 3704ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3705ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3706ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->tag == Iex_Const) { 3707ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* At the moment there should be no 128-bit constants in IR for ARM 3708ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown generated during disassemble. They are represented as Iop_64HLtoV128 3709ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown binary operation and are handled among binary ops. */ 3710ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* But zero can be created by valgrind internal optimizer */ 3711ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->Iex.Const.con->Ico.V128 == 0) { 3712ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegV(env); 3713ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NeonImm(res, ARMNImm_TI(0, 0))); 3714ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 3715ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3716ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ppIRExpr(e); 3717ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vpanic("128-bit constant is not implemented"); 3718ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3719ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3720ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->tag == Iex_Load) { 3721ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegV(env); 3722ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ARMAModeN* am = iselIntExpr_AModeN(env, e->Iex.Load.addr); 3723ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert(ty == Ity_V128); 3724ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NLdStQ(True, res, am)); 3725ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 3726ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3727ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3728ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->tag == Iex_Get) { 3729ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg addr = newVRegI(env); 3730ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegV(env); 3731ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert(ty == Ity_V128); 3732ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_Add32(addr, hregARM_R8(), e->Iex.Get.offset)); 3733ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NLdStQ(True, res, mkARMAModeN_R(addr))); 3734ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 3735ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3736ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 3737ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->tag == Iex_Unop) { 3738ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (e->Iex.Unop.op) { 3739ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_NotV128: { 3740ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DECLARE_PATTERN(p_veqz_8x16); 3741ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DECLARE_PATTERN(p_veqz_16x8); 3742ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DECLARE_PATTERN(p_veqz_32x4); 3743ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DECLARE_PATTERN(p_vcge_8sx16); 3744ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DECLARE_PATTERN(p_vcge_16sx8); 3745ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DECLARE_PATTERN(p_vcge_32sx4); 3746ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DECLARE_PATTERN(p_vcge_8ux16); 3747ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DECLARE_PATTERN(p_vcge_16ux8); 3748ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DECLARE_PATTERN(p_vcge_32ux4); 3749ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEFINE_PATTERN(p_veqz_8x16, 3750ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown unop(Iop_NotV128, unop(Iop_CmpNEZ8x16, bind(0)))); 3751ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEFINE_PATTERN(p_veqz_16x8, 3752ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown unop(Iop_NotV128, unop(Iop_CmpNEZ16x8, bind(0)))); 3753ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEFINE_PATTERN(p_veqz_32x4, 3754ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown unop(Iop_NotV128, unop(Iop_CmpNEZ32x4, bind(0)))); 3755ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEFINE_PATTERN(p_vcge_8sx16, 3756ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown unop(Iop_NotV128, binop(Iop_CmpGT8Sx16, bind(1), bind(0)))); 3757ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEFINE_PATTERN(p_vcge_16sx8, 3758ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown unop(Iop_NotV128, binop(Iop_CmpGT16Sx8, bind(1), bind(0)))); 3759ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEFINE_PATTERN(p_vcge_32sx4, 3760ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown unop(Iop_NotV128, binop(Iop_CmpGT32Sx4, bind(1), bind(0)))); 3761ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEFINE_PATTERN(p_vcge_8ux16, 3762ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown unop(Iop_NotV128, binop(Iop_CmpGT8Ux16, bind(1), bind(0)))); 3763ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEFINE_PATTERN(p_vcge_16ux8, 3764ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown unop(Iop_NotV128, binop(Iop_CmpGT16Ux8, bind(1), bind(0)))); 3765ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEFINE_PATTERN(p_vcge_32ux4, 3766ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown unop(Iop_NotV128, binop(Iop_CmpGT32Ux4, bind(1), bind(0)))); 3767ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (matchIRExpr(&mi, p_veqz_8x16, e)) { 3768ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegV(env); 3769ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg arg = iselNeonExpr(env, mi.bindee[0]); 3770ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnary(ARMneon_EQZ, res, arg, 0, True)); 3771ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 3772ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else if (matchIRExpr(&mi, p_veqz_16x8, e)) { 3773ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegV(env); 3774ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg arg = iselNeonExpr(env, mi.bindee[0]); 3775ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnary(ARMneon_EQZ, res, arg, 1, True)); 3776ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 3777ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else if (matchIRExpr(&mi, p_veqz_32x4, e)) { 3778ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegV(env); 3779ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg arg = iselNeonExpr(env, mi.bindee[0]); 3780ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnary(ARMneon_EQZ, res, arg, 2, True)); 3781ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 3782ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else if (matchIRExpr(&mi, p_vcge_8sx16, e)) { 3783ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegV(env); 3784ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeonExpr(env, mi.bindee[0]); 3785ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeonExpr(env, mi.bindee[1]); 3786ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NBinary(ARMneon_VCGES, 3787ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, argR, 0, True)); 3788ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 3789ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else if (matchIRExpr(&mi, p_vcge_16sx8, e)) { 3790ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegV(env); 3791ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeonExpr(env, mi.bindee[0]); 3792ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeonExpr(env, mi.bindee[1]); 3793ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NBinary(ARMneon_VCGES, 3794ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, argR, 1, True)); 3795ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 3796ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else if (matchIRExpr(&mi, p_vcge_32sx4, e)) { 3797ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegV(env); 3798ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeonExpr(env, mi.bindee[0]); 3799ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeonExpr(env, mi.bindee[1]); 3800ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NBinary(ARMneon_VCGES, 3801ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, argR, 2, True)); 3802ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 3803ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else if (matchIRExpr(&mi, p_vcge_8ux16, e)) { 3804ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegV(env); 3805ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeonExpr(env, mi.bindee[0]); 3806ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeonExpr(env, mi.bindee[1]); 3807ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NBinary(ARMneon_VCGEU, 3808ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, argR, 0, True)); 3809ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 3810ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else if (matchIRExpr(&mi, p_vcge_16ux8, e)) { 3811ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegV(env); 3812ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeonExpr(env, mi.bindee[0]); 3813ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeonExpr(env, mi.bindee[1]); 3814ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NBinary(ARMneon_VCGEU, 3815ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, argR, 1, True)); 3816ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 3817ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else if (matchIRExpr(&mi, p_vcge_32ux4, e)) { 3818ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegV(env); 3819ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeonExpr(env, mi.bindee[0]); 3820ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeonExpr(env, mi.bindee[1]); 3821ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NBinary(ARMneon_VCGEU, 3822ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, argR, 2, True)); 3823ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 3824ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 3825ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegV(env); 3826ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg arg = iselNeonExpr(env, e->Iex.Unop.arg); 3827ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnary(ARMneon_NOT, res, arg, 4, True)); 3828ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 3829ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3830ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3831ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Dup8x16: 3832ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Dup16x8: 3833ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Dup32x4: { 3834ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res, arg; 3835ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size; 3836ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DECLARE_PATTERN(p_vdup_8x16); 3837ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DECLARE_PATTERN(p_vdup_16x8); 3838ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DECLARE_PATTERN(p_vdup_32x4); 3839ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEFINE_PATTERN(p_vdup_8x16, 3840ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown unop(Iop_Dup8x16, binop(Iop_GetElem8x8, bind(0), bind(1)))); 3841ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEFINE_PATTERN(p_vdup_16x8, 3842ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown unop(Iop_Dup16x8, binop(Iop_GetElem16x4, bind(0), bind(1)))); 3843ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEFINE_PATTERN(p_vdup_32x4, 3844ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown unop(Iop_Dup32x4, binop(Iop_GetElem32x2, bind(0), bind(1)))); 3845ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (matchIRExpr(&mi, p_vdup_8x16, e)) { 3846ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt index; 3847ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt imm4; 3848ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (mi.bindee[1]->tag == Iex_Const && 3849ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown typeOfIRExpr(env->type_env, mi.bindee[1]) == Ity_I8) { 3850ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown index = mi.bindee[1]->Iex.Const.con->Ico.U8; 3851ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown imm4 = (index << 1) + 1; 3852ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (index < 8) { 3853ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res = newVRegV(env); 3854ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown arg = iselNeon64Expr(env, mi.bindee[0]); 3855ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnaryS( 3856ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ARMneon_VDUP, 3857ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mkARMNRS(ARMNRS_Reg, res, 0), 3858ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mkARMNRS(ARMNRS_Scalar, arg, index), 3859ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown imm4, True 3860ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown )); 3861ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 3862ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3863ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3864ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else if (matchIRExpr(&mi, p_vdup_16x8, e)) { 3865ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt index; 3866ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt imm4; 3867ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (mi.bindee[1]->tag == Iex_Const && 3868ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown typeOfIRExpr(env->type_env, mi.bindee[1]) == Ity_I8) { 3869ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown index = mi.bindee[1]->Iex.Const.con->Ico.U8; 3870ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown imm4 = (index << 2) + 2; 3871ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (index < 4) { 3872ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res = newVRegV(env); 3873ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown arg = iselNeon64Expr(env, mi.bindee[0]); 3874ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnaryS( 3875ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ARMneon_VDUP, 3876ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mkARMNRS(ARMNRS_Reg, res, 0), 3877ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mkARMNRS(ARMNRS_Scalar, arg, index), 3878ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown imm4, True 3879ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown )); 3880ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 3881ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3882ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3883ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else if (matchIRExpr(&mi, p_vdup_32x4, e)) { 3884ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt index; 3885ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt imm4; 3886ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (mi.bindee[1]->tag == Iex_Const && 3887ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown typeOfIRExpr(env->type_env, mi.bindee[1]) == Ity_I8) { 3888ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown index = mi.bindee[1]->Iex.Const.con->Ico.U8; 3889ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown imm4 = (index << 3) + 4; 3890ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (index < 2) { 3891ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res = newVRegV(env); 3892ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown arg = iselNeon64Expr(env, mi.bindee[0]); 3893ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnaryS( 3894ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ARMneon_VDUP, 3895ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mkARMNRS(ARMNRS_Reg, res, 0), 3896ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mkARMNRS(ARMNRS_Scalar, arg, index), 3897ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown imm4, True 3898ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown )); 3899ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 3900ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3901ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3902ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3903ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown arg = iselIntExpr_R(env, e->Iex.Unop.arg); 3904ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res = newVRegV(env); 3905ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (e->Iex.Unop.op) { 3906ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Dup8x16: size = 0; break; 3907ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Dup16x8: size = 1; break; 3908ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Dup32x4: size = 2; break; 3909ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: vassert(0); 3910ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3911ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnary(ARMneon_DUP, res, arg, size, True)); 3912ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 3913ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3914ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Abs8x16: 3915ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Abs16x8: 3916ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Abs32x4: { 3917ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegV(env); 3918ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg arg = iselNeonExpr(env, e->Iex.Unop.arg); 3919ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size = 0; 3920ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch(e->Iex.Binop.op) { 3921ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Abs8x16: size = 0; break; 3922ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Abs16x8: size = 1; break; 3923ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Abs32x4: size = 2; break; 3924ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: vassert(0); 3925ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3926ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnary(ARMneon_ABS, res, arg, size, True)); 3927ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 3928ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3929ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Reverse64_8x16: 3930ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Reverse64_16x8: 3931ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Reverse64_32x4: { 3932ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegV(env); 3933ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg arg = iselNeonExpr(env, e->Iex.Unop.arg); 3934ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size = 0; 3935ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch(e->Iex.Binop.op) { 3936ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Reverse64_8x16: size = 0; break; 3937ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Reverse64_16x8: size = 1; break; 3938ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Reverse64_32x4: size = 2; break; 3939ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: vassert(0); 3940ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3941ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnary(ARMneon_REV64, 3942ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, arg, size, True)); 3943ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 3944ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3945ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Reverse32_8x16: 3946ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Reverse32_16x8: { 3947ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegV(env); 3948ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg arg = iselNeonExpr(env, e->Iex.Unop.arg); 3949ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size = 0; 3950ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch(e->Iex.Binop.op) { 3951ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Reverse32_8x16: size = 0; break; 3952ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Reverse32_16x8: size = 1; break; 3953ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: vassert(0); 3954ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3955ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnary(ARMneon_REV32, 3956ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, arg, size, True)); 3957ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 3958ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3959ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Reverse16_8x16: { 3960ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegV(env); 3961ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg arg = iselNeonExpr(env, e->Iex.Unop.arg); 3962ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size = 0; 3963ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnary(ARMneon_REV16, 3964ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, arg, size, True)); 3965ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 3966ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3967ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CmpNEZ64x2: { 3968ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg x_lsh = newVRegV(env); 3969ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg x_rsh = newVRegV(env); 3970ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg lsh_amt = newVRegV(env); 3971ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg rsh_amt = newVRegV(env); 3972ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg zero = newVRegV(env); 3973ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg tmp = newVRegV(env); 3974ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg tmp2 = newVRegV(env); 3975ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegV(env); 3976ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg x = newVRegV(env); 3977ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg arg = iselNeonExpr(env, e->Iex.Unop.arg); 3978ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnary(ARMneon_EQZ, tmp2, arg, 2, True)); 3979ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnary(ARMneon_NOT, x, tmp2, 4, True)); 3980ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NeonImm(lsh_amt, ARMNImm_TI(0, 32))); 3981ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NeonImm(zero, ARMNImm_TI(0, 0))); 3982ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NBinary(ARMneon_VSUB, 3983ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown rsh_amt, zero, lsh_amt, 2, True)); 3984ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NShift(ARMneon_VSHL, 3985ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown x_lsh, x, lsh_amt, 3, True)); 3986ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NShift(ARMneon_VSHL, 3987ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown x_rsh, x, rsh_amt, 3, True)); 3988ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NBinary(ARMneon_VORR, 3989ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tmp, x_lsh, x_rsh, 0, True)); 3990ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NBinary(ARMneon_VORR, 3991ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, tmp, x, 0, True)); 3992ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 3993ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 3994ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CmpNEZ8x16: 3995ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CmpNEZ16x8: 3996ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CmpNEZ32x4: { 3997ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegV(env); 3998ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg tmp = newVRegV(env); 3999ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg arg = iselNeonExpr(env, e->Iex.Unop.arg); 4000ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size; 4001ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (e->Iex.Unop.op) { 4002ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CmpNEZ8x16: size = 0; break; 4003ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CmpNEZ16x8: size = 1; break; 4004ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CmpNEZ32x4: size = 2; break; 4005ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: vassert(0); 4006ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4007ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnary(ARMneon_EQZ, tmp, arg, size, True)); 4008ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnary(ARMneon_NOT, res, tmp, 4, True)); 4009ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 4010ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4011b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov case Iop_Widen8Uto16x8: 4012b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov case Iop_Widen16Uto32x4: 4013b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov case Iop_Widen32Uto64x2: { 4014ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegV(env); 4015ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg arg = iselNeon64Expr(env, e->Iex.Unop.arg); 4016ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size; 4017ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (e->Iex.Unop.op) { 4018b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov case Iop_Widen8Uto16x8: size = 0; break; 4019b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov case Iop_Widen16Uto32x4: size = 1; break; 4020b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov case Iop_Widen32Uto64x2: size = 2; break; 4021ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: vassert(0); 4022ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4023ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnary(ARMneon_COPYLU, 4024ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, arg, size, True)); 4025ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 4026ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4027b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov case Iop_Widen8Sto16x8: 4028b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov case Iop_Widen16Sto32x4: 4029b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov case Iop_Widen32Sto64x2: { 4030ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegV(env); 4031ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg arg = iselNeon64Expr(env, e->Iex.Unop.arg); 4032ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size; 4033ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (e->Iex.Unop.op) { 4034b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov case Iop_Widen8Sto16x8: size = 0; break; 4035b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov case Iop_Widen16Sto32x4: size = 1; break; 4036b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov case Iop_Widen32Sto64x2: size = 2; break; 4037ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: vassert(0); 4038ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4039ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnary(ARMneon_COPYLS, 4040ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, arg, size, True)); 4041ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 4042ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4043ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_PwAddL8Sx16: 4044ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_PwAddL16Sx8: 4045ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_PwAddL32Sx4: { 4046ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegV(env); 4047ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg arg = iselNeonExpr(env, e->Iex.Unop.arg); 4048ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size = 0; 4049ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch(e->Iex.Binop.op) { 4050ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_PwAddL8Sx16: size = 0; break; 4051ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_PwAddL16Sx8: size = 1; break; 4052ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_PwAddL32Sx4: size = 2; break; 4053ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: vassert(0); 4054ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4055ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnary(ARMneon_PADDLS, 4056ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, arg, size, True)); 4057ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 4058ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4059ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_PwAddL8Ux16: 4060ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_PwAddL16Ux8: 4061ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_PwAddL32Ux4: { 4062ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegV(env); 4063ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg arg = iselNeonExpr(env, e->Iex.Unop.arg); 4064ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size = 0; 4065ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch(e->Iex.Binop.op) { 4066ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_PwAddL8Ux16: size = 0; break; 4067ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_PwAddL16Ux8: size = 1; break; 4068ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_PwAddL32Ux4: size = 2; break; 4069ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: vassert(0); 4070ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4071ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnary(ARMneon_PADDLU, 4072ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, arg, size, True)); 4073ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 4074ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4075ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Cnt8x16: { 4076ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegV(env); 4077ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg arg = iselNeonExpr(env, e->Iex.Unop.arg); 4078ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size = 0; 4079ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnary(ARMneon_CNT, res, arg, size, True)); 4080ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 4081ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4082ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Clz8Sx16: 4083ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Clz16Sx8: 4084ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Clz32Sx4: { 4085ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegV(env); 4086ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg arg = iselNeonExpr(env, e->Iex.Unop.arg); 4087ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size = 0; 4088ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch(e->Iex.Binop.op) { 4089ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Clz8Sx16: size = 0; break; 4090ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Clz16Sx8: size = 1; break; 4091ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Clz32Sx4: size = 2; break; 4092ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: vassert(0); 4093ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4094ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnary(ARMneon_CLZ, res, arg, size, True)); 4095ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 4096ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4097ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Cls8Sx16: 4098ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Cls16Sx8: 4099ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Cls32Sx4: { 4100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegV(env); 4101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg arg = iselNeonExpr(env, e->Iex.Unop.arg); 4102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size = 0; 4103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch(e->Iex.Binop.op) { 4104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Cls8Sx16: size = 0; break; 4105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Cls16Sx8: size = 1; break; 4106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Cls32Sx4: size = 2; break; 4107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: vassert(0); 4108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnary(ARMneon_CLS, res, arg, size, True)); 4110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 4111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_FtoI32Sx4_RZ: { 4113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegV(env); 4114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg arg = iselNeonExpr(env, e->Iex.Unop.arg); 4115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnary(ARMneon_VCVTFtoS, 4116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, arg, 2, True)); 4117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 4118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_FtoI32Ux4_RZ: { 4120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegV(env); 4121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg arg = iselNeonExpr(env, e->Iex.Unop.arg); 4122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnary(ARMneon_VCVTFtoU, 4123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, arg, 2, True)); 4124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 4125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_I32StoFx4: { 4127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegV(env); 4128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg arg = iselNeonExpr(env, e->Iex.Unop.arg); 4129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnary(ARMneon_VCVTStoF, 4130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, arg, 2, True)); 4131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 4132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_I32UtoFx4: { 4134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegV(env); 4135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg arg = iselNeonExpr(env, e->Iex.Unop.arg); 4136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnary(ARMneon_VCVTUtoF, 4137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, arg, 2, True)); 4138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 4139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_F16toF32x4: { 4141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegV(env); 4142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg arg = iselNeon64Expr(env, e->Iex.Unop.arg); 4143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnary(ARMneon_VCVTF16toF32, 4144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, arg, 2, True)); 4145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 4146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Recip32Fx4: { 4148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegV(env); 4149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeonExpr(env, e->Iex.Unop.arg); 4150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnary(ARMneon_VRECIPF, 4151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, 0, True)); 4152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 4153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Recip32x4: { 4155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegV(env); 4156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeonExpr(env, e->Iex.Unop.arg); 4157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnary(ARMneon_VRECIP, 4158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, 0, True)); 4159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 4160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Abs32Fx4: { 4162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DECLARE_PATTERN(p_vabd_32fx4); 4163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEFINE_PATTERN(p_vabd_32fx4, 4164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown unop(Iop_Abs32Fx4, 4165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown binop(Iop_Sub32Fx4, 4166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown bind(0), 4167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown bind(1)))); 4168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (matchIRExpr(&mi, p_vabd_32fx4, e)) { 4169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegV(env); 4170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeonExpr(env, mi.bindee[0]); 4171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeonExpr(env, mi.bindee[1]); 4172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NBinary(ARMneon_VABDFP, 4173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, argR, 0, True)); 4174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 4175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 4176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegV(env); 4177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeonExpr(env, e->Iex.Unop.arg); 4178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnary(ARMneon_VABSFP, 4179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, 0, True)); 4180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 4181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Rsqrte32Fx4: { 4184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegV(env); 4185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeonExpr(env, e->Iex.Unop.arg); 4186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnary(ARMneon_VRSQRTEFP, 4187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, 0, True)); 4188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 4189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Rsqrte32x4: { 4191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegV(env); 4192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeonExpr(env, e->Iex.Unop.arg); 4193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnary(ARMneon_VRSQRTE, 4194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, 0, True)); 4195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 4196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Neg32Fx4: { 4198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegV(env); 4199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg arg = iselNeonExpr(env, e->Iex.Unop.arg); 4200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnary(ARMneon_VNEGF, 4201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, arg, 0, True)); 4202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 4203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* ... */ 4205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: 4206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 4207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 4210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->tag == Iex_Binop) { 4211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (e->Iex.Binop.op) { 4212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_64HLtoV128: 4213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Try to match into single "VMOV reg, imm" instruction */ 4214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->Iex.Binop.arg1->tag == Iex_Const && 4215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown e->Iex.Binop.arg2->tag == Iex_Const && 4216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown typeOfIRExpr(env->type_env, e->Iex.Binop.arg1) == Ity_I64 && 4217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown typeOfIRExpr(env->type_env, e->Iex.Binop.arg2) == Ity_I64 && 4218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown e->Iex.Binop.arg1->Iex.Const.con->Ico.U64 == 4219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown e->Iex.Binop.arg2->Iex.Const.con->Ico.U64) { 4220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ULong imm64 = e->Iex.Binop.arg2->Iex.Const.con->Ico.U64; 4221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ARMNImm *imm = Imm64_to_ARMNImm(imm64); 4222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (imm) { 4223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegV(env); 4224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NeonImm(res, imm)); 4225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 4226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if ((imm64 >> 32) == 0LL && 4228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (imm = Imm64_to_ARMNImm(imm64 | (imm64 << 32))) != NULL) { 4229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg tmp1 = newVRegV(env); 4230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg tmp2 = newVRegV(env); 4231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegV(env); 4232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (imm->type < 10) { 4233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NeonImm(tmp1, ARMNImm_TI(9,0x0f))); 4234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NeonImm(tmp2, imm)); 4235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NBinary(ARMneon_VAND, 4236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, tmp1, tmp2, 4, True)); 4237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 4238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if ((imm64 & 0xFFFFFFFFLL) == 0LL && 4241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (imm = Imm64_to_ARMNImm(imm64 | (imm64 >> 32))) != NULL) { 4242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg tmp1 = newVRegV(env); 4243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg tmp2 = newVRegV(env); 4244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegV(env); 4245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (imm->type < 10) { 4246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NeonImm(tmp1, ARMNImm_TI(9,0xf0))); 4247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NeonImm(tmp2, imm)); 4248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NBinary(ARMneon_VAND, 4249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, tmp1, tmp2, 4, True)); 4250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 4251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4254b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov /* Does not match "VMOV Reg, Imm" form. We'll have to do 4255b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov it the slow way. */ 4256b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov { 4257b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov /* local scope */ 4258b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov /* Done via the stack for ease of use. */ 4259b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov /* FIXME: assumes little endian host */ 4260b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov HReg w3, w2, w1, w0; 4261b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov HReg res = newVRegV(env); 4262b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov ARMAMode1* sp_0 = ARMAMode1_RI(hregARM_R13(), 0); 4263b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov ARMAMode1* sp_4 = ARMAMode1_RI(hregARM_R13(), 4); 4264b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov ARMAMode1* sp_8 = ARMAMode1_RI(hregARM_R13(), 8); 4265b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov ARMAMode1* sp_12 = ARMAMode1_RI(hregARM_R13(), 12); 4266b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov ARMRI84* c_16 = ARMRI84_I84(16,0); 4267b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov /* Make space for SP */ 4268b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov addInstr(env, ARMInstr_Alu(ARMalu_SUB, hregARM_R13(), 4269b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov hregARM_R13(), c_16)); 4270b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 4271b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov /* Store the less significant 64 bits */ 4272b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov iselInt64Expr(&w1, &w0, env, e->Iex.Binop.arg2); 4273b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov addInstr(env, ARMInstr_LdSt32(False/*store*/, w0, sp_0)); 4274b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov addInstr(env, ARMInstr_LdSt32(False/*store*/, w1, sp_4)); 4275b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 4276b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov /* Store the more significant 64 bits */ 4277b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov iselInt64Expr(&w3, &w2, env, e->Iex.Binop.arg1); 4278b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov addInstr(env, ARMInstr_LdSt32(False/*store*/, w2, sp_8)); 4279b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov addInstr(env, ARMInstr_LdSt32(False/*store*/, w3, sp_12)); 4280b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 4281b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov /* Load result back from stack. */ 4282b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov addInstr(env, ARMInstr_NLdStQ(True/*load*/, res, 4283b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov mkARMAModeN_R(hregARM_R13()))); 4284b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 4285b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov /* Restore SP */ 4286b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov addInstr(env, ARMInstr_Alu(ARMalu_ADD, hregARM_R13(), 4287b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov hregARM_R13(), c_16)); 4288b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov return res; 4289b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } /* local scope */ 4290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown goto neon_expr_bad; 4291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_AndV128: { 4292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegV(env); 4293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeonExpr(env, e->Iex.Binop.arg1); 4294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeonExpr(env, e->Iex.Binop.arg2); 4295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NBinary(ARMneon_VAND, 4296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, argR, 4, True)); 4297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 4298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_OrV128: { 4300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegV(env); 4301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeonExpr(env, e->Iex.Binop.arg1); 4302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeonExpr(env, e->Iex.Binop.arg2); 4303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NBinary(ARMneon_VORR, 4304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, argR, 4, True)); 4305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 4306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_XorV128: { 4308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegV(env); 4309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeonExpr(env, e->Iex.Binop.arg1); 4310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeonExpr(env, e->Iex.Binop.arg2); 4311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NBinary(ARMneon_VXOR, 4312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, argR, 4, True)); 4313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 4314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Add8x16: 4316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Add16x8: 4317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Add32x4: 4318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Add64x2: { 4319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* 4320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown FIXME: remove this if not used 4321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DECLARE_PATTERN(p_vrhadd_32sx4); 4322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ULong one = (1LL << 32) | 1LL; 4323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DEFINE_PATTERN(p_vrhadd_32sx4, 4324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown binop(Iop_Add32x4, 4325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown binop(Iop_Add32x4, 4326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown binop(Iop_SarN32x4, 4327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown bind(0), 4328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mkU8(1)), 4329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown binop(Iop_SarN32x4, 4330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown bind(1), 4331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mkU8(1))), 4332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown binop(Iop_SarN32x4, 4333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown binop(Iop_Add32x4, 4334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown binop(Iop_Add32x4, 4335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown binop(Iop_AndV128, 4336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown bind(0), 4337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mkU128(one)), 4338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown binop(Iop_AndV128, 4339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown bind(1), 4340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mkU128(one))), 4341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mkU128(one)), 4342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mkU8(1)))); 4343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */ 4344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegV(env); 4345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeonExpr(env, e->Iex.Binop.arg1); 4346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeonExpr(env, e->Iex.Binop.arg2); 4347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size; 4348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (e->Iex.Binop.op) { 4349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Add8x16: size = 0; break; 4350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Add16x8: size = 1; break; 4351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Add32x4: size = 2; break; 4352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Add64x2: size = 3; break; 4353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: 4354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ppIROp(e->Iex.Binop.op); 4355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vpanic("Illegal element size in VADD"); 4356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NBinary(ARMneon_VADD, 4358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, argR, size, True)); 4359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 4360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Add32Fx4: { 4362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegV(env); 4363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeonExpr(env, e->Iex.Binop.arg1); 4364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeonExpr(env, e->Iex.Binop.arg2); 4365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size = 0; 4366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NBinary(ARMneon_VADDFP, 4367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, argR, size, True)); 4368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 4369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Recps32Fx4: { 4371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegV(env); 4372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeonExpr(env, e->Iex.Binop.arg1); 4373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeonExpr(env, e->Iex.Binop.arg2); 4374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size = 0; 4375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NBinary(ARMneon_VRECPS, 4376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, argR, size, True)); 4377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 4378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Rsqrts32Fx4: { 4380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegV(env); 4381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeonExpr(env, e->Iex.Binop.arg1); 4382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeonExpr(env, e->Iex.Binop.arg2); 4383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size = 0; 4384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NBinary(ARMneon_VRSQRTS, 4385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, argR, size, True)); 4386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 4387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_InterleaveEvenLanes8x16: 4389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_InterleaveEvenLanes16x8: 4390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_InterleaveEvenLanes32x4: 4391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_InterleaveOddLanes8x16: 4392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_InterleaveOddLanes16x8: 4393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_InterleaveOddLanes32x4: { 4394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg tmp = newVRegV(env); 4395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegV(env); 4396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeonExpr(env, e->Iex.Binop.arg1); 4397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeonExpr(env, e->Iex.Binop.arg2); 4398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size; 4399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt is_lo; 4400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (e->Iex.Binop.op) { 4401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_InterleaveEvenLanes8x16: is_lo = 0; size = 0; break; 4402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_InterleaveOddLanes8x16: is_lo = 1; size = 0; break; 4403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_InterleaveEvenLanes16x8: is_lo = 0; size = 1; break; 4404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_InterleaveOddLanes16x8: is_lo = 1; size = 1; break; 4405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_InterleaveEvenLanes32x4: is_lo = 0; size = 2; break; 4406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_InterleaveOddLanes32x4: is_lo = 1; size = 2; break; 4407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: 4408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ppIROp(e->Iex.Binop.op); 4409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vpanic("Illegal element size in VTRN"); 4410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (is_lo) { 4412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnary(ARMneon_COPY, 4413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tmp, argL, 4, True)); 4414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnary(ARMneon_COPY, 4415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argR, 4, True)); 4416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NDual(ARMneon_TRN, 4417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, tmp, size, True)); 4418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 4419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnary(ARMneon_COPY, 4420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tmp, argR, 4, True)); 4421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnary(ARMneon_COPY, 4422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, 4, True)); 4423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NDual(ARMneon_TRN, 4424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tmp, res, size, True)); 4425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 4427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_InterleaveHI8x16: 4429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_InterleaveHI16x8: 4430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_InterleaveHI32x4: 4431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_InterleaveLO8x16: 4432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_InterleaveLO16x8: 4433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_InterleaveLO32x4: { 4434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg tmp = newVRegV(env); 4435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegV(env); 4436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeonExpr(env, e->Iex.Binop.arg1); 4437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeonExpr(env, e->Iex.Binop.arg2); 4438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size; 4439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt is_lo; 4440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (e->Iex.Binop.op) { 4441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_InterleaveHI8x16: is_lo = 1; size = 0; break; 4442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_InterleaveLO8x16: is_lo = 0; size = 0; break; 4443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_InterleaveHI16x8: is_lo = 1; size = 1; break; 4444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_InterleaveLO16x8: is_lo = 0; size = 1; break; 4445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_InterleaveHI32x4: is_lo = 1; size = 2; break; 4446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_InterleaveLO32x4: is_lo = 0; size = 2; break; 4447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: 4448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ppIROp(e->Iex.Binop.op); 4449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vpanic("Illegal element size in VZIP"); 4450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (is_lo) { 4452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnary(ARMneon_COPY, 4453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tmp, argL, 4, True)); 4454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnary(ARMneon_COPY, 4455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argR, 4, True)); 4456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NDual(ARMneon_ZIP, 4457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, tmp, size, True)); 4458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 4459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnary(ARMneon_COPY, 4460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tmp, argR, 4, True)); 4461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnary(ARMneon_COPY, 4462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, 4, True)); 4463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NDual(ARMneon_ZIP, 4464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tmp, res, size, True)); 4465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 4467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CatOddLanes8x16: 4469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CatOddLanes16x8: 4470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CatOddLanes32x4: 4471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CatEvenLanes8x16: 4472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CatEvenLanes16x8: 4473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CatEvenLanes32x4: { 4474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg tmp = newVRegV(env); 4475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegV(env); 4476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeonExpr(env, e->Iex.Binop.arg1); 4477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeonExpr(env, e->Iex.Binop.arg2); 4478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size; 4479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt is_lo; 4480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (e->Iex.Binop.op) { 4481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CatOddLanes8x16: is_lo = 1; size = 0; break; 4482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CatEvenLanes8x16: is_lo = 0; size = 0; break; 4483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CatOddLanes16x8: is_lo = 1; size = 1; break; 4484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CatEvenLanes16x8: is_lo = 0; size = 1; break; 4485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CatOddLanes32x4: is_lo = 1; size = 2; break; 4486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CatEvenLanes32x4: is_lo = 0; size = 2; break; 4487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: 4488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ppIROp(e->Iex.Binop.op); 4489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vpanic("Illegal element size in VUZP"); 4490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (is_lo) { 4492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnary(ARMneon_COPY, 4493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tmp, argL, 4, True)); 4494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnary(ARMneon_COPY, 4495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argR, 4, True)); 4496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NDual(ARMneon_UZP, 4497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, tmp, size, True)); 4498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 4499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnary(ARMneon_COPY, 4500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tmp, argR, 4, True)); 4501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnary(ARMneon_COPY, 4502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, 4, True)); 4503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NDual(ARMneon_UZP, 4504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tmp, res, size, True)); 4505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4506ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 4507ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4508ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QAdd8Ux16: 4509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QAdd16Ux8: 4510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QAdd32Ux4: 4511ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QAdd64Ux2: { 4512ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegV(env); 4513ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeonExpr(env, e->Iex.Binop.arg1); 4514ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeonExpr(env, e->Iex.Binop.arg2); 4515ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size; 4516ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (e->Iex.Binop.op) { 4517ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QAdd8Ux16: size = 0; break; 4518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QAdd16Ux8: size = 1; break; 4519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QAdd32Ux4: size = 2; break; 4520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QAdd64Ux2: size = 3; break; 4521ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: 4522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ppIROp(e->Iex.Binop.op); 4523ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vpanic("Illegal element size in VQADDU"); 4524ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4525ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NBinary(ARMneon_VQADDU, 4526ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, argR, size, True)); 4527ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 4528ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4529ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QAdd8Sx16: 4530ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QAdd16Sx8: 4531ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QAdd32Sx4: 4532ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QAdd64Sx2: { 4533ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegV(env); 4534ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeonExpr(env, e->Iex.Binop.arg1); 4535ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeonExpr(env, e->Iex.Binop.arg2); 4536ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size; 4537ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (e->Iex.Binop.op) { 4538ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QAdd8Sx16: size = 0; break; 4539ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QAdd16Sx8: size = 1; break; 4540ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QAdd32Sx4: size = 2; break; 4541ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QAdd64Sx2: size = 3; break; 4542ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: 4543ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ppIROp(e->Iex.Binop.op); 4544ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vpanic("Illegal element size in VQADDS"); 4545ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4546ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NBinary(ARMneon_VQADDS, 4547ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, argR, size, True)); 4548ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 4549ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4550ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Sub8x16: 4551ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Sub16x8: 4552ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Sub32x4: 4553ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Sub64x2: { 4554ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegV(env); 4555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeonExpr(env, e->Iex.Binop.arg1); 4556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeonExpr(env, e->Iex.Binop.arg2); 4557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size; 4558ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (e->Iex.Binop.op) { 4559ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Sub8x16: size = 0; break; 4560ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Sub16x8: size = 1; break; 4561ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Sub32x4: size = 2; break; 4562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Sub64x2: size = 3; break; 4563ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: 4564ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ppIROp(e->Iex.Binop.op); 4565ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vpanic("Illegal element size in VSUB"); 4566ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4567ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NBinary(ARMneon_VSUB, 4568ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, argR, size, True)); 4569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 4570ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4571ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Sub32Fx4: { 4572ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegV(env); 4573ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeonExpr(env, e->Iex.Binop.arg1); 4574ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeonExpr(env, e->Iex.Binop.arg2); 4575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size = 0; 4576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NBinary(ARMneon_VSUBFP, 4577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, argR, size, True)); 4578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 4579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QSub8Ux16: 4581ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QSub16Ux8: 4582ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QSub32Ux4: 4583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QSub64Ux2: { 4584ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegV(env); 4585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeonExpr(env, e->Iex.Binop.arg1); 4586ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeonExpr(env, e->Iex.Binop.arg2); 4587ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size; 4588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (e->Iex.Binop.op) { 4589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QSub8Ux16: size = 0; break; 4590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QSub16Ux8: size = 1; break; 4591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QSub32Ux4: size = 2; break; 4592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QSub64Ux2: size = 3; break; 4593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: 4594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ppIROp(e->Iex.Binop.op); 4595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vpanic("Illegal element size in VQSUBU"); 4596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NBinary(ARMneon_VQSUBU, 4598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, argR, size, True)); 4599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 4600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QSub8Sx16: 4602ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QSub16Sx8: 4603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QSub32Sx4: 4604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QSub64Sx2: { 4605ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegV(env); 4606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeonExpr(env, e->Iex.Binop.arg1); 4607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeonExpr(env, e->Iex.Binop.arg2); 4608ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size; 4609ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (e->Iex.Binop.op) { 4610ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QSub8Sx16: size = 0; break; 4611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QSub16Sx8: size = 1; break; 4612ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QSub32Sx4: size = 2; break; 4613ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QSub64Sx2: size = 3; break; 4614ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: 4615ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ppIROp(e->Iex.Binop.op); 4616ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vpanic("Illegal element size in VQSUBS"); 4617ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4618ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NBinary(ARMneon_VQSUBS, 4619ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, argR, size, True)); 4620ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 4621ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4622ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Max8Ux16: 4623ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Max16Ux8: 4624ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Max32Ux4: { 4625ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegV(env); 4626ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeonExpr(env, e->Iex.Binop.arg1); 4627ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeonExpr(env, e->Iex.Binop.arg2); 4628ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size; 4629ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (e->Iex.Binop.op) { 4630ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Max8Ux16: size = 0; break; 4631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Max16Ux8: size = 1; break; 4632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Max32Ux4: size = 2; break; 4633ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: vpanic("Illegal element size in VMAXU"); 4634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NBinary(ARMneon_VMAXU, 4636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, argR, size, True)); 4637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 4638ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4639ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Max8Sx16: 4640ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Max16Sx8: 4641ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Max32Sx4: { 4642ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegV(env); 4643ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeonExpr(env, e->Iex.Binop.arg1); 4644ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeonExpr(env, e->Iex.Binop.arg2); 4645ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size; 4646ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (e->Iex.Binop.op) { 4647ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Max8Sx16: size = 0; break; 4648ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Max16Sx8: size = 1; break; 4649ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Max32Sx4: size = 2; break; 4650ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: vpanic("Illegal element size in VMAXU"); 4651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4652ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NBinary(ARMneon_VMAXS, 4653ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, argR, size, True)); 4654ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 4655ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4656ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Min8Ux16: 4657ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Min16Ux8: 4658ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Min32Ux4: { 4659ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegV(env); 4660ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeonExpr(env, e->Iex.Binop.arg1); 4661ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeonExpr(env, e->Iex.Binop.arg2); 4662ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size; 4663ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (e->Iex.Binop.op) { 4664ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Min8Ux16: size = 0; break; 4665ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Min16Ux8: size = 1; break; 4666ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Min32Ux4: size = 2; break; 4667ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: vpanic("Illegal element size in VMAXU"); 4668ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4669ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NBinary(ARMneon_VMINU, 4670ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, argR, size, True)); 4671ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 4672ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4673ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Min8Sx16: 4674ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Min16Sx8: 4675ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Min32Sx4: { 4676ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegV(env); 4677ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeonExpr(env, e->Iex.Binop.arg1); 4678ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeonExpr(env, e->Iex.Binop.arg2); 4679ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size; 4680ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (e->Iex.Binop.op) { 4681ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Min8Sx16: size = 0; break; 4682ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Min16Sx8: size = 1; break; 4683ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Min32Sx4: size = 2; break; 4684ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: vpanic("Illegal element size in VMAXU"); 4685ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4686ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NBinary(ARMneon_VMINS, 4687ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, argR, size, True)); 4688ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 4689ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4690ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Sar8x16: 4691ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Sar16x8: 4692ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Sar32x4: 4693ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Sar64x2: { 4694ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegV(env); 4695ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeonExpr(env, e->Iex.Binop.arg1); 4696ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeonExpr(env, e->Iex.Binop.arg2); 4697ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR2 = newVRegV(env); 4698ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg zero = newVRegV(env); 4699ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size; 4700ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (e->Iex.Binop.op) { 4701ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Sar8x16: size = 0; break; 4702ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Sar16x8: size = 1; break; 4703ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Sar32x4: size = 2; break; 4704ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Sar64x2: size = 3; break; 4705ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: vassert(0); 4706ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4707ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NeonImm(zero, ARMNImm_TI(0,0))); 4708ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NBinary(ARMneon_VSUB, 4709ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown argR2, zero, argR, size, True)); 4710ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NShift(ARMneon_VSAL, 4711ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, argR2, size, True)); 4712ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 4713ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4714ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Sal8x16: 4715ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Sal16x8: 4716ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Sal32x4: 4717ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Sal64x2: { 4718ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegV(env); 4719ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeonExpr(env, e->Iex.Binop.arg1); 4720ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeonExpr(env, e->Iex.Binop.arg2); 4721ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size; 4722ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (e->Iex.Binop.op) { 4723ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Sal8x16: size = 0; break; 4724ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Sal16x8: size = 1; break; 4725ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Sal32x4: size = 2; break; 4726ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Sal64x2: size = 3; break; 4727ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: vassert(0); 4728ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4729ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NShift(ARMneon_VSAL, 4730ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, argR, size, True)); 4731ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 4732ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4733ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Shr8x16: 4734ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Shr16x8: 4735ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Shr32x4: 4736ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Shr64x2: { 4737ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegV(env); 4738ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeonExpr(env, e->Iex.Binop.arg1); 4739ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeonExpr(env, e->Iex.Binop.arg2); 4740ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR2 = newVRegV(env); 4741ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg zero = newVRegV(env); 4742ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size; 4743ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (e->Iex.Binop.op) { 4744ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Shr8x16: size = 0; break; 4745ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Shr16x8: size = 1; break; 4746ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Shr32x4: size = 2; break; 4747ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Shr64x2: size = 3; break; 4748ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: vassert(0); 4749ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4750ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NeonImm(zero, ARMNImm_TI(0,0))); 4751ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NBinary(ARMneon_VSUB, 4752ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown argR2, zero, argR, size, True)); 4753ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NShift(ARMneon_VSHL, 4754ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, argR2, size, True)); 4755ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 4756ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4757ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Shl8x16: 4758ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Shl16x8: 4759ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Shl32x4: 4760ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Shl64x2: { 4761ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegV(env); 4762ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeonExpr(env, e->Iex.Binop.arg1); 4763ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeonExpr(env, e->Iex.Binop.arg2); 4764ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size; 4765ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (e->Iex.Binop.op) { 4766ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Shl8x16: size = 0; break; 4767ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Shl16x8: size = 1; break; 4768ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Shl32x4: size = 2; break; 4769ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Shl64x2: size = 3; break; 4770ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: vassert(0); 4771ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4772ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NShift(ARMneon_VSHL, 4773ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, argR, size, True)); 4774ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 4775ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4776ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QShl8x16: 4777ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QShl16x8: 4778ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QShl32x4: 4779ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QShl64x2: { 4780ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegV(env); 4781ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeonExpr(env, e->Iex.Binop.arg1); 4782ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeonExpr(env, e->Iex.Binop.arg2); 4783ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size; 4784ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (e->Iex.Binop.op) { 4785ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QShl8x16: size = 0; break; 4786ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QShl16x8: size = 1; break; 4787ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QShl32x4: size = 2; break; 4788ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QShl64x2: size = 3; break; 4789ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: vassert(0); 4790ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4791ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NShift(ARMneon_VQSHL, 4792ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, argR, size, True)); 4793ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 4794ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4795ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QSal8x16: 4796ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QSal16x8: 4797ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QSal32x4: 4798ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QSal64x2: { 4799ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegV(env); 4800ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeonExpr(env, e->Iex.Binop.arg1); 4801ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeonExpr(env, e->Iex.Binop.arg2); 4802ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size; 4803ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (e->Iex.Binop.op) { 4804ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QSal8x16: size = 0; break; 4805ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QSal16x8: size = 1; break; 4806ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QSal32x4: size = 2; break; 4807ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QSal64x2: size = 3; break; 4808ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: vassert(0); 4809ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4810ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NShift(ARMneon_VQSAL, 4811ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, argR, size, True)); 4812ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 4813ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4814ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QShlN8x16: 4815ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QShlN16x8: 4816ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QShlN32x4: 4817ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QShlN64x2: { 4818ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegV(env); 4819ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeonExpr(env, e->Iex.Binop.arg1); 4820ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size, imm; 4821ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->Iex.Binop.arg2->tag != Iex_Const || 4822ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown typeOfIRExpr(env->type_env, e->Iex.Binop.arg2) != Ity_I8) { 4823ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vpanic("ARM taget supports Iop_QShlNAxB with constant " 4824ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "second argument only\n"); 4825ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4826ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown imm = e->Iex.Binop.arg2->Iex.Const.con->Ico.U8; 4827ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (e->Iex.Binop.op) { 4828ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QShlN8x16: size = 8 | imm; break; 4829ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QShlN16x8: size = 16 | imm; break; 4830ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QShlN32x4: size = 32 | imm; break; 4831ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QShlN64x2: size = 64 | imm; break; 4832ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: vassert(0); 4833ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4834ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnary(ARMneon_VQSHLNUU, 4835ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, size, True)); 4836ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 4837ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4838ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QShlN8Sx16: 4839ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QShlN16Sx8: 4840ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QShlN32Sx4: 4841ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QShlN64Sx2: { 4842ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegV(env); 4843ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeonExpr(env, e->Iex.Binop.arg1); 4844ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size, imm; 4845ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->Iex.Binop.arg2->tag != Iex_Const || 4846ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown typeOfIRExpr(env->type_env, e->Iex.Binop.arg2) != Ity_I8) { 4847ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vpanic("ARM taget supports Iop_QShlNASxB with constant " 4848ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "second argument only\n"); 4849ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4850ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown imm = e->Iex.Binop.arg2->Iex.Const.con->Ico.U8; 4851ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (e->Iex.Binop.op) { 4852ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QShlN8Sx16: size = 8 | imm; break; 4853ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QShlN16Sx8: size = 16 | imm; break; 4854ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QShlN32Sx4: size = 32 | imm; break; 4855ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QShlN64Sx2: size = 64 | imm; break; 4856ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: vassert(0); 4857ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4858ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnary(ARMneon_VQSHLNUS, 4859ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, size, True)); 4860ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 4861ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4862ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QSalN8x16: 4863ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QSalN16x8: 4864ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QSalN32x4: 4865ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QSalN64x2: { 4866ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegV(env); 4867ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeonExpr(env, e->Iex.Binop.arg1); 4868ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size, imm; 4869ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->Iex.Binop.arg2->tag != Iex_Const || 4870ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown typeOfIRExpr(env->type_env, e->Iex.Binop.arg2) != Ity_I8) { 4871ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vpanic("ARM taget supports Iop_QShlNAxB with constant " 4872ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "second argument only\n"); 4873ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4874ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown imm = e->Iex.Binop.arg2->Iex.Const.con->Ico.U8; 4875ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (e->Iex.Binop.op) { 4876ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QSalN8x16: size = 8 | imm; break; 4877ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QSalN16x8: size = 16 | imm; break; 4878ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QSalN32x4: size = 32 | imm; break; 4879ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QSalN64x2: size = 64 | imm; break; 4880ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: vassert(0); 4881ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4882ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnary(ARMneon_VQSHLNSS, 4883ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, size, True)); 4884ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 4885ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4886ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_ShrN8x16: 4887ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_ShrN16x8: 4888ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_ShrN32x4: 4889ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_ShrN64x2: { 4890ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegV(env); 4891ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg tmp = newVRegV(env); 4892ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeonExpr(env, e->Iex.Binop.arg1); 4893ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselIntExpr_R(env, e->Iex.Binop.arg2); 4894ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR2 = newVRegI(env); 4895ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size; 4896ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (e->Iex.Binop.op) { 4897ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_ShrN8x16: size = 0; break; 4898ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_ShrN16x8: size = 1; break; 4899ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_ShrN32x4: size = 2; break; 4900ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_ShrN64x2: size = 3; break; 4901ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: vassert(0); 4902ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4903ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_Unary(ARMun_NEG, argR2, argR)); 4904ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnary(ARMneon_DUP, 4905ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tmp, argR2, 0, True)); 4906ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NShift(ARMneon_VSHL, 4907ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, tmp, size, True)); 4908ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 4909ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4910ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_ShlN8x16: 4911ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_ShlN16x8: 4912ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_ShlN32x4: 4913ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_ShlN64x2: { 4914ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegV(env); 4915ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg tmp = newVRegV(env); 4916ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeonExpr(env, e->Iex.Binop.arg1); 4917ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselIntExpr_R(env, e->Iex.Binop.arg2); 4918ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size; 4919ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (e->Iex.Binop.op) { 4920ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_ShlN8x16: size = 0; break; 4921ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_ShlN16x8: size = 1; break; 4922ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_ShlN32x4: size = 2; break; 4923ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_ShlN64x2: size = 3; break; 4924ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: vassert(0); 4925ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4926ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnary(ARMneon_DUP, tmp, argR, 0, True)); 4927ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NShift(ARMneon_VSHL, 4928ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, tmp, size, True)); 4929ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 4930ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4931ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_SarN8x16: 4932ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_SarN16x8: 4933ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_SarN32x4: 4934ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_SarN64x2: { 4935ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegV(env); 4936ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg tmp = newVRegV(env); 4937ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeonExpr(env, e->Iex.Binop.arg1); 4938ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselIntExpr_R(env, e->Iex.Binop.arg2); 4939ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR2 = newVRegI(env); 4940ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size; 4941ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (e->Iex.Binop.op) { 4942ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_SarN8x16: size = 0; break; 4943ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_SarN16x8: size = 1; break; 4944ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_SarN32x4: size = 2; break; 4945ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_SarN64x2: size = 3; break; 4946ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: vassert(0); 4947ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4948ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_Unary(ARMun_NEG, argR2, argR)); 4949ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnary(ARMneon_DUP, tmp, argR2, 0, True)); 4950ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NShift(ARMneon_VSAL, 4951ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, tmp, size, True)); 4952ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 4953ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4954ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CmpGT8Ux16: 4955ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CmpGT16Ux8: 4956ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CmpGT32Ux4: { 4957ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegV(env); 4958ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeonExpr(env, e->Iex.Binop.arg1); 4959ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeonExpr(env, e->Iex.Binop.arg2); 4960ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size; 4961ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (e->Iex.Binop.op) { 4962ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CmpGT8Ux16: size = 0; break; 4963ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CmpGT16Ux8: size = 1; break; 4964ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CmpGT32Ux4: size = 2; break; 4965ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: vassert(0); 4966ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4967ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NBinary(ARMneon_VCGTU, 4968ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, argR, size, True)); 4969ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 4970ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4971ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CmpGT8Sx16: 4972ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CmpGT16Sx8: 4973ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CmpGT32Sx4: { 4974ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegV(env); 4975ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeonExpr(env, e->Iex.Binop.arg1); 4976ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeonExpr(env, e->Iex.Binop.arg2); 4977ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size; 4978ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (e->Iex.Binop.op) { 4979ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CmpGT8Sx16: size = 0; break; 4980ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CmpGT16Sx8: size = 1; break; 4981ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CmpGT32Sx4: size = 2; break; 4982ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: vassert(0); 4983ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4984ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NBinary(ARMneon_VCGTS, 4985ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, argR, size, True)); 4986ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 4987ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 4988ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CmpEQ8x16: 4989ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CmpEQ16x8: 4990ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CmpEQ32x4: { 4991ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegV(env); 4992ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeonExpr(env, e->Iex.Binop.arg1); 4993ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeonExpr(env, e->Iex.Binop.arg2); 4994ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size; 4995ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (e->Iex.Binop.op) { 4996ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CmpEQ8x16: size = 0; break; 4997ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CmpEQ16x8: size = 1; break; 4998ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CmpEQ32x4: size = 2; break; 4999ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: vassert(0); 5000ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5001ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NBinary(ARMneon_VCEQ, 5002ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, argR, size, True)); 5003ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 5004ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5005ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Mul8x16: 5006ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Mul16x8: 5007ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Mul32x4: { 5008ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegV(env); 5009ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeonExpr(env, e->Iex.Binop.arg1); 5010ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeonExpr(env, e->Iex.Binop.arg2); 5011ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size = 0; 5012ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch(e->Iex.Binop.op) { 5013ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Mul8x16: size = 0; break; 5014ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Mul16x8: size = 1; break; 5015ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Mul32x4: size = 2; break; 5016ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: vassert(0); 5017ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5018ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NBinary(ARMneon_VMUL, 5019ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, argR, size, True)); 5020ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 5021ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5022ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Mul32Fx4: { 5023ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegV(env); 5024ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeonExpr(env, e->Iex.Binop.arg1); 5025ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeonExpr(env, e->Iex.Binop.arg2); 5026ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size = 0; 5027ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NBinary(ARMneon_VMULFP, 5028ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, argR, size, True)); 5029ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 5030ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5031ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Mull8Ux8: 5032ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Mull16Ux4: 5033ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Mull32Ux2: { 5034ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegV(env); 5035ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeon64Expr(env, e->Iex.Binop.arg1); 5036ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeon64Expr(env, e->Iex.Binop.arg2); 5037ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size = 0; 5038ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch(e->Iex.Binop.op) { 5039ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Mull8Ux8: size = 0; break; 5040ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Mull16Ux4: size = 1; break; 5041ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Mull32Ux2: size = 2; break; 5042ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: vassert(0); 5043ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5044ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NBinary(ARMneon_VMULLU, 5045ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, argR, size, True)); 5046ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 5047ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5048ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 5049ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Mull8Sx8: 5050ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Mull16Sx4: 5051ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Mull32Sx2: { 5052ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegV(env); 5053ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeon64Expr(env, e->Iex.Binop.arg1); 5054ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeon64Expr(env, e->Iex.Binop.arg2); 5055ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size = 0; 5056ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch(e->Iex.Binop.op) { 5057ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Mull8Sx8: size = 0; break; 5058ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Mull16Sx4: size = 1; break; 5059ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Mull32Sx2: size = 2; break; 5060ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: vassert(0); 5061ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5062ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NBinary(ARMneon_VMULLS, 5063ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, argR, size, True)); 5064ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 5065ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5066ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 5067ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QDMulHi16Sx8: 5068ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QDMulHi32Sx4: { 5069ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegV(env); 5070ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeonExpr(env, e->Iex.Binop.arg1); 5071ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeonExpr(env, e->Iex.Binop.arg2); 5072ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size = 0; 5073ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch(e->Iex.Binop.op) { 5074ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QDMulHi16Sx8: size = 1; break; 5075ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QDMulHi32Sx4: size = 2; break; 5076ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: vassert(0); 5077ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5078ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NBinary(ARMneon_VQDMULH, 5079ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, argR, size, True)); 5080ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 5081ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5082ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 5083ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QRDMulHi16Sx8: 5084ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QRDMulHi32Sx4: { 5085ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegV(env); 5086ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeonExpr(env, e->Iex.Binop.arg1); 5087ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeonExpr(env, e->Iex.Binop.arg2); 5088ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size = 0; 5089ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch(e->Iex.Binop.op) { 5090ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QRDMulHi16Sx8: size = 1; break; 5091ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QRDMulHi32Sx4: size = 2; break; 5092ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: vassert(0); 5093ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5094ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NBinary(ARMneon_VQRDMULH, 5095ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, argR, size, True)); 5096ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 5097ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5098ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 5099ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QDMulLong16Sx4: 5100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QDMulLong32Sx2: { 5101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegV(env); 5102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeon64Expr(env, e->Iex.Binop.arg1); 5103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeon64Expr(env, e->Iex.Binop.arg2); 5104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size = 0; 5105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch(e->Iex.Binop.op) { 5106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QDMulLong16Sx4: size = 1; break; 5107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_QDMulLong32Sx2: size = 2; break; 5108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: vassert(0); 5109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NBinary(ARMneon_VQDMULL, 5111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, argR, size, True)); 5112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 5113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_PolynomialMul8x16: { 5115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegV(env); 5116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeonExpr(env, e->Iex.Binop.arg1); 5117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeonExpr(env, e->Iex.Binop.arg2); 5118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size = 0; 5119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NBinary(ARMneon_VMULP, 5120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, argR, size, True)); 5121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 5122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Max32Fx4: { 5124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegV(env); 5125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeonExpr(env, e->Iex.Binop.arg1); 5126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeonExpr(env, e->Iex.Binop.arg2); 5127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NBinary(ARMneon_VMAXF, 5128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, argR, 2, True)); 5129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 5130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Min32Fx4: { 5132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegV(env); 5133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeonExpr(env, e->Iex.Binop.arg1); 5134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeonExpr(env, e->Iex.Binop.arg2); 5135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NBinary(ARMneon_VMINF, 5136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, argR, 2, True)); 5137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 5138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_PwMax32Fx4: { 5140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegV(env); 5141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeonExpr(env, e->Iex.Binop.arg1); 5142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeonExpr(env, e->Iex.Binop.arg2); 5143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NBinary(ARMneon_VPMAXF, 5144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, argR, 2, True)); 5145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 5146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_PwMin32Fx4: { 5148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegV(env); 5149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeonExpr(env, e->Iex.Binop.arg1); 5150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeonExpr(env, e->Iex.Binop.arg2); 5151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NBinary(ARMneon_VPMINF, 5152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, argR, 2, True)); 5153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 5154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CmpGT32Fx4: { 5156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegV(env); 5157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeonExpr(env, e->Iex.Binop.arg1); 5158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeonExpr(env, e->Iex.Binop.arg2); 5159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NBinary(ARMneon_VCGTF, 5160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, argR, 2, True)); 5161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 5162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CmpGE32Fx4: { 5164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegV(env); 5165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeonExpr(env, e->Iex.Binop.arg1); 5166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeonExpr(env, e->Iex.Binop.arg2); 5167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NBinary(ARMneon_VCGEF, 5168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, argR, 2, True)); 5169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 5170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_CmpEQ32Fx4: { 5172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegV(env); 5173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeonExpr(env, e->Iex.Binop.arg1); 5174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeonExpr(env, e->Iex.Binop.arg2); 5175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NBinary(ARMneon_VCEQF, 5176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, argR, 2, True)); 5177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 5178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 5180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_PolynomialMull8x8: { 5181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegV(env); 5182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeon64Expr(env, e->Iex.Binop.arg1); 5183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeon64Expr(env, e->Iex.Binop.arg2); 5184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size = 0; 5185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NBinary(ARMneon_VMULLP, 5186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, argR, size, True)); 5187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 5188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_F32ToFixed32Ux4_RZ: 5190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_F32ToFixed32Sx4_RZ: 5191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Fixed32UToF32x4_RN: 5192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Fixed32SToF32x4_RN: { 5193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegV(env); 5194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg arg = iselNeonExpr(env, e->Iex.Binop.arg1); 5195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ARMNeonUnOp op; 5196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt imm6; 5197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->Iex.Binop.arg2->tag != Iex_Const || 5198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown typeOfIRExpr(env->type_env, e->Iex.Binop.arg2) != Ity_I8) { 5199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vpanic("ARM supports FP <-> Fixed conversion with constant " 5200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "second argument less than 33 only\n"); 5201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown imm6 = e->Iex.Binop.arg2->Iex.Const.con->Ico.U8; 5203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert(imm6 <= 32 && imm6 > 0); 5204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown imm6 = 64 - imm6; 5205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch(e->Iex.Binop.op) { 5206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_F32ToFixed32Ux4_RZ: op = ARMneon_VCVTFtoFixedU; break; 5207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_F32ToFixed32Sx4_RZ: op = ARMneon_VCVTFtoFixedS; break; 5208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Fixed32UToF32x4_RN: op = ARMneon_VCVTFixedUtoF; break; 5209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_Fixed32SToF32x4_RN: op = ARMneon_VCVTFixedStoF; break; 5210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: vassert(0); 5211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnary(op, res, arg, imm6, True)); 5213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 5214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* 5216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown FIXME remove if not used 5217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_VDup8x16: 5218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_VDup16x8: 5219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_VDup32x4: { 5220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegV(env); 5221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeon64Expr(env, e->Iex.Binop.arg1); 5222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt imm4; 5223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt index; 5224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->Iex.Binop.arg2->tag != Iex_Const || 5225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown typeOfIRExpr(env->type_env, e->Iex.Binop.arg2) != Ity_I8) { 5226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vpanic("ARM supports Iop_VDup with constant " 5227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "second argument less than 16 only\n"); 5228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown index = e->Iex.Binop.arg2->Iex.Const.con->Ico.U8; 5230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch(e->Iex.Binop.op) { 5231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_VDup8x16: imm4 = (index << 1) + 1; break; 5232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_VDup16x8: imm4 = (index << 2) + 2; break; 5233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_VDup32x4: imm4 = (index << 3) + 4; break; 5234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: vassert(0); 5235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (imm4 >= 16) { 5237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vpanic("ARM supports Iop_VDup with constant " 5238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "second argument less than 16 only\n"); 5239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnary(ARMneon_VDUP, 5241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, imm4, True)); 5242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 5243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */ 5245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_PwAdd8x16: 5246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_PwAdd16x8: 5247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_PwAdd32x4: { 5248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegV(env); 5249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argL = iselNeonExpr(env, e->Iex.Binop.arg1); 5250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg argR = iselNeonExpr(env, e->Iex.Binop.arg2); 5251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt size = 0; 5252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch(e->Iex.Binop.op) { 5253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_PwAdd8x16: size = 0; break; 5254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_PwAdd16x8: size = 1; break; 5255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_PwAdd32x4: size = 2; break; 5256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: vassert(0); 5257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NBinary(ARMneon_VPADD, 5259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, argR, size, True)); 5260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 5261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* ... */ 5263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: 5264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 5265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 5268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->tag == Iex_Triop) { 5269663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng IRTriop *triop = e->Iex.Triop.details; 5270663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 5271663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng switch (triop->op) { 5272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_ExtractV128: { 5273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegV(env); 5274663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng HReg argL = iselNeonExpr(env, triop->arg1); 5275663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng HReg argR = iselNeonExpr(env, triop->arg2); 5276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt imm4; 5277663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng if (triop->arg3->tag != Iex_Const || 5278663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng typeOfIRExpr(env->type_env, triop->arg3) != Ity_I8) { 5279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vpanic("ARM target supports Iop_ExtractV128 with constant " 5280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "third argument less than 16 only\n"); 5281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5282663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng imm4 = triop->arg3->Iex.Const.con->Ico.U8; 5283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (imm4 >= 16) { 5284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vpanic("ARM target supports Iop_ExtractV128 with constant " 5285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "third argument less than 16 only\n"); 5286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NBinary(ARMneon_VEXT, 5288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res, argL, argR, imm4, True)); 5289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 5290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: 5292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 5293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 5296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->tag == Iex_Mux0X) { 5297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg r8; 5298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg rX = iselNeonExpr(env, e->Iex.Mux0X.exprX); 5299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg r0 = iselNeonExpr(env, e->Iex.Mux0X.expr0); 5300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg dst = newVRegV(env); 5301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnary(ARMneon_COPY, dst, rX, 4, True)); 5302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown r8 = iselIntExpr_R(env, e->Iex.Mux0X.cond); 5303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_CmpOrTst(False/*!isCmp*/, r8, 5304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ARMRI84_I84(0xFF,0))); 5305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NCMovQ(ARMcc_EQ, dst, r0)); 5306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return dst; 5307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 5309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown neon_expr_bad: 5310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ppIRExpr(e); 5311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vpanic("iselNeonExpr_wrk"); 5312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 5313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 5314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------*/ 5315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- ISEL: Floating point expressions (64 bit) ---*/ 5316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------*/ 5317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 5318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Compute a 64-bit floating point value into a register, the identity 5319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown of which is returned. As with iselIntExpr_R, the reg may be either 5320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown real or virtual; in any case it must not be changed by subsequent 5321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown code emitted by the caller. */ 5322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 5323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic HReg iselDblExpr ( ISelEnv* env, IRExpr* e ) 5324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 5325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg r = iselDblExpr_wrk( env, e ); 5326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# if 0 5327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vex_printf("\n"); ppIRExpr(e); vex_printf("\n"); 5328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 5329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert(hregClass(r) == HRcFlt64); 5330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert(hregIsVirtual(r)); 5331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return r; 5332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 5333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 5334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* DO NOT CALL THIS DIRECTLY */ 5335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic HReg iselDblExpr_wrk ( ISelEnv* env, IRExpr* e ) 5336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 5337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRType ty = typeOfIRExpr(env->type_env,e); 5338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert(e); 5339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert(ty == Ity_F64); 5340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 5341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->tag == Iex_RdTmp) { 5342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return lookupIRTemp(env, e->Iex.RdTmp.tmp); 5343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 5345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->tag == Iex_Const) { 5346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Just handle the zero case. */ 5347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRConst* con = e->Iex.Const.con; 5348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (con->tag == Ico_F64i && con->Ico.F64i == 0ULL) { 5349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg z32 = newVRegI(env); 5350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg dst = newVRegD(env); 5351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_Imm32(z32, 0)); 5352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_VXferD(True/*toD*/, dst, z32, z32)); 5353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return dst; 5354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 5357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->tag == Iex_Load && e->Iex.Load.end == Iend_LE) { 5358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ARMAModeV* am; 5359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegD(env); 5360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert(e->Iex.Load.ty == Ity_F64); 5361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown am = iselIntExpr_AModeV(env, e->Iex.Load.addr); 5362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_VLdStD(True/*isLoad*/, res, am)); 5363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 5364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 5366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->tag == Iex_Get) { 5367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // XXX This won't work if offset > 1020 or is not 0 % 4. 5368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // In which case we'll have to generate more longwinded code. 5369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ARMAModeV* am = mkARMAModeV(hregARM_R8(), e->Iex.Get.offset); 5370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegD(env); 5371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_VLdStD(True/*isLoad*/, res, am)); 5372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 5373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 5375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->tag == Iex_Unop) { 5376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (e->Iex.Unop.op) { 5377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_ReinterpI64asF64: { 5378663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng if (env->hwcaps & VEX_HWCAPS_ARM_NEON) { 5379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return iselNeon64Expr(env, e->Iex.Unop.arg); 5380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 5381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg srcHi, srcLo; 5382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg dst = newVRegD(env); 5383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown iselInt64Expr(&srcHi, &srcLo, env, e->Iex.Unop.arg); 5384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_VXferD(True/*toD*/, dst, srcHi, srcLo)); 5385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return dst; 5386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_NegF64: { 5389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg src = iselDblExpr(env, e->Iex.Unop.arg); 5390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg dst = newVRegD(env); 5391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_VUnaryD(ARMvfpu_NEG, dst, src)); 5392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return dst; 5393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_AbsF64: { 5395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg src = iselDblExpr(env, e->Iex.Unop.arg); 5396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg dst = newVRegD(env); 5397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_VUnaryD(ARMvfpu_ABS, dst, src)); 5398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return dst; 5399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_F32toF64: { 5401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg src = iselFltExpr(env, e->Iex.Unop.arg); 5402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg dst = newVRegD(env); 5403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_VCvtSD(True/*sToD*/, dst, src)); 5404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return dst; 5405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_I32UtoF64: 5407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_I32StoF64: { 5408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg src = iselIntExpr_R(env, e->Iex.Unop.arg); 5409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg f32 = newVRegF(env); 5410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg dst = newVRegD(env); 5411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bool syned = e->Iex.Unop.op == Iop_I32StoF64; 5412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* VMOV f32, src */ 5413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_VXferS(True/*toS*/, f32, src)); 5414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* FSITOD dst, f32 */ 5415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_VCvtID(True/*iToD*/, syned, 5416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown dst, f32)); 5417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return dst; 5418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: 5420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 5421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 5424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->tag == Iex_Binop) { 5425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (e->Iex.Binop.op) { 5426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_SqrtF64: { 5427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* first arg is rounding mode; we ignore it. */ 5428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg src = iselDblExpr(env, e->Iex.Binop.arg2); 5429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg dst = newVRegD(env); 5430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_VUnaryD(ARMvfpu_SQRT, dst, src)); 5431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return dst; 5432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: 5434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 5435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 5438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->tag == Iex_Triop) { 5439663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng IRTriop *triop = e->Iex.Triop.details; 5440663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 5441663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng switch (triop->op) { 5442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_DivF64: 5443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_MulF64: 5444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_AddF64: 5445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_SubF64: { 5446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ARMVfpOp op = 0; /*INVALID*/ 5447663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng HReg argL = iselDblExpr(env, triop->arg2); 5448663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng HReg argR = iselDblExpr(env, triop->arg3); 5449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg dst = newVRegD(env); 5450663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng switch (triop->op) { 5451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_DivF64: op = ARMvfp_DIV; break; 5452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_MulF64: op = ARMvfp_MUL; break; 5453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_AddF64: op = ARMvfp_ADD; break; 5454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_SubF64: op = ARMvfp_SUB; break; 5455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: vassert(0); 5456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_VAluD(op, dst, argL, argR)); 5458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return dst; 5459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: 5461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 5462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 5465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->tag == Iex_Mux0X) { 5466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (ty == Ity_F64 5467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && typeOfIRExpr(env->type_env,e->Iex.Mux0X.cond) == Ity_I8) { 5468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg r8; 5469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg rX = iselDblExpr(env, e->Iex.Mux0X.exprX); 5470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg r0 = iselDblExpr(env, e->Iex.Mux0X.expr0); 5471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg dst = newVRegD(env); 5472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_VUnaryD(ARMvfpu_COPY, dst, rX)); 5473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown r8 = iselIntExpr_R(env, e->Iex.Mux0X.cond); 5474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_CmpOrTst(False/*!isCmp*/, r8, 5475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ARMRI84_I84(0xFF,0))); 5476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_VCMovD(ARMcc_EQ, dst, r0)); 5477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return dst; 5478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 5481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ppIRExpr(e); 5482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vpanic("iselDblExpr_wrk"); 5483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 5484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 5485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 5486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------*/ 5487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- ISEL: Floating point expressions (32 bit) ---*/ 5488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------*/ 5489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 5490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Compute a 64-bit floating point value into a register, the identity 5491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown of which is returned. As with iselIntExpr_R, the reg may be either 5492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown real or virtual; in any case it must not be changed by subsequent 5493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown code emitted by the caller. */ 5494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 5495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic HReg iselFltExpr ( ISelEnv* env, IRExpr* e ) 5496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 5497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg r = iselFltExpr_wrk( env, e ); 5498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# if 0 5499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vex_printf("\n"); ppIRExpr(e); vex_printf("\n"); 5500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 5501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert(hregClass(r) == HRcFlt32); 5502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert(hregIsVirtual(r)); 5503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return r; 5504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 5505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 5506ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* DO NOT CALL THIS DIRECTLY */ 5507ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic HReg iselFltExpr_wrk ( ISelEnv* env, IRExpr* e ) 5508ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 5509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRType ty = typeOfIRExpr(env->type_env,e); 5510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert(e); 5511ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert(ty == Ity_F32); 5512ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 5513ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->tag == Iex_RdTmp) { 5514ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return lookupIRTemp(env, e->Iex.RdTmp.tmp); 5515ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5516ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 5517ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->tag == Iex_Load && e->Iex.Load.end == Iend_LE) { 5518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ARMAModeV* am; 5519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegF(env); 5520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert(e->Iex.Load.ty == Ity_F32); 5521ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown am = iselIntExpr_AModeV(env, e->Iex.Load.addr); 5522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_VLdStS(True/*isLoad*/, res, am)); 5523ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 5524ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5525ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 5526ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->tag == Iex_Get) { 5527ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // XXX This won't work if offset > 1020 or is not 0 % 4. 5528ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // In which case we'll have to generate more longwinded code. 5529ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ARMAModeV* am = mkARMAModeV(hregARM_R8(), e->Iex.Get.offset); 5530ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg res = newVRegF(env); 5531ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_VLdStS(True/*isLoad*/, res, am)); 5532ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 5533ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5534ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 5535ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->tag == Iex_Unop) { 5536ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (e->Iex.Unop.op) { 5537ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_ReinterpI32asF32: { 5538ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg dst = newVRegF(env); 5539ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg src = iselIntExpr_R(env, e->Iex.Unop.arg); 5540ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_VXferS(True/*toS*/, dst, src)); 5541ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return dst; 5542ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5543ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_NegF32: { 5544ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg src = iselFltExpr(env, e->Iex.Unop.arg); 5545ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg dst = newVRegF(env); 5546ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_VUnaryS(ARMvfpu_NEG, dst, src)); 5547ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return dst; 5548ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5549ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_AbsF32: { 5550ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg src = iselFltExpr(env, e->Iex.Unop.arg); 5551ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg dst = newVRegF(env); 5552ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_VUnaryS(ARMvfpu_ABS, dst, src)); 5553ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return dst; 5554ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: 5556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 5557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5558ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5559ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 5560ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->tag == Iex_Binop) { 5561ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (e->Iex.Binop.op) { 5562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_SqrtF32: { 5563ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* first arg is rounding mode; we ignore it. */ 5564ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg src = iselFltExpr(env, e->Iex.Binop.arg2); 5565ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg dst = newVRegF(env); 5566ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_VUnaryS(ARMvfpu_SQRT, dst, src)); 5567ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return dst; 5568ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_F64toF32: { 5570ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg valD = iselDblExpr(env, e->Iex.Binop.arg2); 5571ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown set_VFP_rounding_mode(env, e->Iex.Binop.arg1); 5572ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg valS = newVRegF(env); 5573ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* FCVTSD valS, valD */ 5574ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_VCvtSD(False/*!sToD*/, valS, valD)); 5575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown set_VFP_rounding_default(env); 5576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return valS; 5577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: 5579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 5580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5581ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5582ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 5583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->tag == Iex_Triop) { 5584663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng IRTriop *triop = e->Iex.Triop.details; 5585663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 5586663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng switch (triop->op) { 5587ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_DivF32: 5588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_MulF32: 5589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_AddF32: 5590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_SubF32: { 5591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ARMVfpOp op = 0; /*INVALID*/ 5592663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng HReg argL = iselFltExpr(env, triop->arg2); 5593663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng HReg argR = iselFltExpr(env, triop->arg3); 5594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg dst = newVRegF(env); 5595663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng switch (triop->op) { 5596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_DivF32: op = ARMvfp_DIV; break; 5597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_MulF32: op = ARMvfp_MUL; break; 5598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_AddF32: op = ARMvfp_ADD; break; 5599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Iop_SubF32: op = ARMvfp_SUB; break; 5600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: vassert(0); 5601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5602ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_VAluS(op, dst, argL, argR)); 5603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return dst; 5604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5605ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: 5606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 5607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5608ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5609ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 5610ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (e->tag == Iex_Mux0X) { 5611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (ty == Ity_F32 5612ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && typeOfIRExpr(env->type_env,e->Iex.Mux0X.cond) == Ity_I8) { 5613ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg r8; 5614ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg rX = iselFltExpr(env, e->Iex.Mux0X.exprX); 5615ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg r0 = iselFltExpr(env, e->Iex.Mux0X.expr0); 5616ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg dst = newVRegF(env); 5617ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_VUnaryS(ARMvfpu_COPY, dst, rX)); 5618ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown r8 = iselIntExpr_R(env, e->Iex.Mux0X.cond); 5619ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_CmpOrTst(False/*!isCmp*/, r8, 5620ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ARMRI84_I84(0xFF,0))); 5621ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_VCMovS(ARMcc_EQ, dst, r0)); 5622ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return dst; 5623ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5624ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5625ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 5626ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ppIRExpr(e); 5627ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vpanic("iselFltExpr_wrk"); 5628ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 5629ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 5630ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 5631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------*/ 5632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- ISEL: Statements ---*/ 5633ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------*/ 5634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 5635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void iselStmt ( ISelEnv* env, IRStmt* stmt ) 5636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 5637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (vex_traceflags & VEX_TRACE_VCODE) { 5638ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vex_printf("\n-- "); 5639ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ppIRStmt(stmt); 5640ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vex_printf("\n"); 5641ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5642ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (stmt->tag) { 5643ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 5644ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* --------- STORE --------- */ 5645ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* little-endian write to memory */ 5646ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Ist_Store: { 5647ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRType tya = typeOfIRExpr(env->type_env, stmt->Ist.Store.addr); 5648ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRType tyd = typeOfIRExpr(env->type_env, stmt->Ist.Store.data); 5649ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IREndness end = stmt->Ist.Store.end; 5650ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 5651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (tya != Ity_I32 || end != Iend_LE) 5652ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown goto stmt_fail; 5653ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 5654ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (tyd == Ity_I32) { 5655ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg rD = iselIntExpr_R(env, stmt->Ist.Store.data); 5656ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ARMAMode1* am = iselIntExpr_AMode1(env, stmt->Ist.Store.addr); 5657ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_LdSt32(False/*!isLoad*/, rD, am)); 5658ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return; 5659ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5660ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (tyd == Ity_I16) { 5661ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg rD = iselIntExpr_R(env, stmt->Ist.Store.data); 5662ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ARMAMode2* am = iselIntExpr_AMode2(env, stmt->Ist.Store.addr); 5663ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_LdSt16(False/*!isLoad*/, 5664ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown False/*!isSignedLoad*/, rD, am)); 5665ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return; 5666ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5667ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (tyd == Ity_I8) { 5668ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg rD = iselIntExpr_R(env, stmt->Ist.Store.data); 5669ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ARMAMode1* am = iselIntExpr_AMode1(env, stmt->Ist.Store.addr); 5670ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_LdSt8U(False/*!isLoad*/, rD, am)); 5671ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return; 5672ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5673ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (tyd == Ity_I64) { 5674663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng if (env->hwcaps & VEX_HWCAPS_ARM_NEON) { 5675ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg dD = iselNeon64Expr(env, stmt->Ist.Store.data); 5676ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ARMAModeN* am = iselIntExpr_AModeN(env, stmt->Ist.Store.addr); 5677ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NLdStD(False, dD, am)); 5678ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 5679ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg rDhi, rDlo, rA; 5680ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown iselInt64Expr(&rDhi, &rDlo, env, stmt->Ist.Store.data); 5681ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown rA = iselIntExpr_R(env, stmt->Ist.Store.addr); 5682ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_LdSt32(False/*!load*/, rDhi, 5683ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ARMAMode1_RI(rA,4))); 5684ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_LdSt32(False/*!load*/, rDlo, 5685ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ARMAMode1_RI(rA,0))); 5686ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5687ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return; 5688ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5689ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (tyd == Ity_F64) { 5690ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg dD = iselDblExpr(env, stmt->Ist.Store.data); 5691ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ARMAModeV* am = iselIntExpr_AModeV(env, stmt->Ist.Store.addr); 5692ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_VLdStD(False/*!isLoad*/, dD, am)); 5693ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return; 5694ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5695ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (tyd == Ity_F32) { 5696ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg fD = iselFltExpr(env, stmt->Ist.Store.data); 5697ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ARMAModeV* am = iselIntExpr_AModeV(env, stmt->Ist.Store.addr); 5698ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_VLdStS(False/*!isLoad*/, fD, am)); 5699ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return; 5700ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5701ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (tyd == Ity_V128) { 5702ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg qD = iselNeonExpr(env, stmt->Ist.Store.data); 5703ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ARMAModeN* am = iselIntExpr_AModeN(env, stmt->Ist.Store.addr); 5704ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NLdStQ(False, qD, am)); 5705ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return; 5706ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5707ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 5708ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 5709ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5710ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 5711ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* --------- PUT --------- */ 5712ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* write guest state, fixed offset */ 5713ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Ist_Put: { 5714ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRType tyd = typeOfIRExpr(env->type_env, stmt->Ist.Put.data); 5715ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 5716ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (tyd == Ity_I32) { 5717ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg rD = iselIntExpr_R(env, stmt->Ist.Put.data); 5718ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ARMAMode1* am = ARMAMode1_RI(hregARM_R8(), stmt->Ist.Put.offset); 5719ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_LdSt32(False/*!isLoad*/, rD, am)); 5720ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return; 5721ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5722ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (tyd == Ity_I64) { 5723663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng if (env->hwcaps & VEX_HWCAPS_ARM_NEON) { 5724ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg addr = newVRegI(env); 5725ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg qD = iselNeon64Expr(env, stmt->Ist.Put.data); 5726ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_Add32(addr, hregARM_R8(), 5727ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown stmt->Ist.Put.offset)); 5728ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NLdStD(False, qD, mkARMAModeN_R(addr))); 5729ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 5730ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg rDhi, rDlo; 5731ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ARMAMode1* am0 = ARMAMode1_RI(hregARM_R8(), 5732ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown stmt->Ist.Put.offset + 0); 5733ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ARMAMode1* am4 = ARMAMode1_RI(hregARM_R8(), 5734ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown stmt->Ist.Put.offset + 4); 5735ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown iselInt64Expr(&rDhi, &rDlo, env, stmt->Ist.Put.data); 5736ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_LdSt32(False/*!isLoad*/, rDhi, am4)); 5737ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_LdSt32(False/*!isLoad*/, rDlo, am0)); 5738ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5739ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return; 5740ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5741ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (tyd == Ity_F64) { 5742ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // XXX This won't work if offset > 1020 or is not 0 % 4. 5743ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // In which case we'll have to generate more longwinded code. 5744ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ARMAModeV* am = mkARMAModeV(hregARM_R8(), stmt->Ist.Put.offset); 5745ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg rD = iselDblExpr(env, stmt->Ist.Put.data); 5746ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_VLdStD(False/*!isLoad*/, rD, am)); 5747ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return; 5748ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5749ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (tyd == Ity_F32) { 5750ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // XXX This won't work if offset > 1020 or is not 0 % 4. 5751ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // In which case we'll have to generate more longwinded code. 5752ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ARMAModeV* am = mkARMAModeV(hregARM_R8(), stmt->Ist.Put.offset); 5753ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg rD = iselFltExpr(env, stmt->Ist.Put.data); 5754ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_VLdStS(False/*!isLoad*/, rD, am)); 5755ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return; 5756ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5757ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (tyd == Ity_V128) { 5758ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg addr = newVRegI(env); 5759ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg qD = iselNeonExpr(env, stmt->Ist.Put.data); 5760ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_Add32(addr, hregARM_R8(), 5761ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown stmt->Ist.Put.offset)); 5762ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NLdStQ(False, qD, mkARMAModeN_R(addr))); 5763ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return; 5764ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5765ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 5766ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5767ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 5768ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz /* --------- Indexed PUT --------- */ 5769ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz /* write guest state, run-time offset */ 5770ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz case Ist_PutI: { 5771ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz ARMAMode2* am2 5772ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz = genGuestArrayOffset( 5773ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz env, stmt->Ist.PutI.descr, 5774ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz stmt->Ist.PutI.ix, stmt->Ist.PutI.bias ); 5775ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz 5776ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz IRType tyd = typeOfIRExpr(env->type_env, stmt->Ist.PutI.data); 5777ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz 5778ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz if (tyd == Ity_I8) { 5779ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz HReg reg = iselIntExpr_R(env, stmt->Ist.PutI.data); 5780ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz addInstr(env, ARMInstr_StoreB(reg, am2)); 5781ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz return; 5782ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz } 5783ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz// CAB: Ity_I32, Ity_I16 ? 5784ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz break; 5785ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz } 5786ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 5787ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* --------- TMP --------- */ 5788ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* assign value to temporary */ 5789ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Ist_WrTmp: { 5790ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRTemp tmp = stmt->Ist.WrTmp.tmp; 5791ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRType ty = typeOfIRTemp(env->type_env, tmp); 5792ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 5793ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (ty == Ity_I32 || ty == Ity_I16 || ty == Ity_I8) { 5794ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ARMRI84* ri84 = iselIntExpr_RI84(NULL, False, 5795ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown env, stmt->Ist.WrTmp.data); 5796ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg dst = lookupIRTemp(env, tmp); 5797ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_Mov(dst,ri84)); 5798ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return; 5799ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5800ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (ty == Ity_I1) { 5801ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg dst = lookupIRTemp(env, tmp); 5802ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ARMCondCode cond = iselCondCode(env, stmt->Ist.WrTmp.data); 5803ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_Mov(dst, ARMRI84_I84(0,0))); 5804ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_CMov(cond, dst, ARMRI84_I84(1,0))); 5805ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return; 5806ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5807ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (ty == Ity_I64) { 5808663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng if (env->hwcaps & VEX_HWCAPS_ARM_NEON) { 5809ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg src = iselNeon64Expr(env, stmt->Ist.WrTmp.data); 5810ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg dst = lookupIRTemp(env, tmp); 5811ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnary(ARMneon_COPY, dst, src, 4, False)); 5812ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 5813ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg rHi, rLo, dstHi, dstLo; 5814ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown iselInt64Expr(&rHi,&rLo, env, stmt->Ist.WrTmp.data); 5815ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown lookupIRTemp64( &dstHi, &dstLo, env, tmp); 5816ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, mk_iMOVds_RR(dstHi, rHi) ); 5817ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, mk_iMOVds_RR(dstLo, rLo) ); 5818ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5819ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return; 5820ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5821ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (ty == Ity_F64) { 5822ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg src = iselDblExpr(env, stmt->Ist.WrTmp.data); 5823ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg dst = lookupIRTemp(env, tmp); 5824ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_VUnaryD(ARMvfpu_COPY, dst, src)); 5825ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return; 5826ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5827ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (ty == Ity_F32) { 5828ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg src = iselFltExpr(env, stmt->Ist.WrTmp.data); 5829ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg dst = lookupIRTemp(env, tmp); 5830ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_VUnaryS(ARMvfpu_COPY, dst, src)); 5831ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return; 5832ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5833ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (ty == Ity_V128) { 5834ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg src = iselNeonExpr(env, stmt->Ist.WrTmp.data); 5835ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg dst = lookupIRTemp(env, tmp); 5836ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_NUnary(ARMneon_COPY, dst, src, 4, True)); 5837ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return; 5838ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5839ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 5840ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5841ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 5842ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* --------- Call to DIRTY helper --------- */ 5843ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* call complex ("dirty") helper function */ 5844ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Ist_Dirty: { 5845ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRType retty; 5846ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRDirty* d = stmt->Ist.Dirty.details; 5847ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bool passBBP = False; 5848ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 5849ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (d->nFxState == 0) 5850ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert(!d->needsBBP); 5851ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 5852ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown passBBP = toBool(d->nFxState > 0 && d->needsBBP); 5853ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 5854ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Marshal args, do the call, clear stack. */ 5855ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bool ok = doHelperCall( env, passBBP, d->guard, d->cee, d->args ); 5856ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!ok) 5857ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; /* will go to stmt_fail: */ 5858ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 5859ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Now figure out what to do with the returned value, if any. */ 5860ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (d->tmp == IRTemp_INVALID) 5861ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* No return value. Nothing to do. */ 5862ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return; 5863ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 5864ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown retty = typeOfIRTemp(env->type_env, d->tmp); 5865ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 5866ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (retty == Ity_I64) { 5867663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng if (env->hwcaps & VEX_HWCAPS_ARM_NEON) { 5868ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg tmp = lookupIRTemp(env, d->tmp); 5869ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_VXferD(True, tmp, hregARM_R1(), 5870ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown hregARM_R0())); 5871ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 5872ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg dstHi, dstLo; 5873ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* The returned value is in r1:r0. Park it in the 5874ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown register-pair associated with tmp. */ 5875ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown lookupIRTemp64( &dstHi, &dstLo, env, d->tmp); 5876ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, mk_iMOVds_RR(dstHi, hregARM_R1()) ); 5877ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, mk_iMOVds_RR(dstLo, hregARM_R0()) ); 5878ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5879ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return; 5880ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5881ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (retty == Ity_I32 || retty == Ity_I16 || retty == Ity_I8) { 5882ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* The returned value is in r0. Park it in the register 5883ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown associated with tmp. */ 5884ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg dst = lookupIRTemp(env, d->tmp); 5885ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, mk_iMOVds_RR(dst, hregARM_R0()) ); 5886ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return; 5887ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5888ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 5889ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 5890ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5891ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 5892ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* --------- Load Linked and Store Conditional --------- */ 5893ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Ist_LLSC: { 5894ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (stmt->Ist.LLSC.storedata == NULL) { 5895ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* LL */ 5896ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRTemp res = stmt->Ist.LLSC.result; 5897ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRType ty = typeOfIRTemp(env->type_env, res); 5898b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (ty == Ity_I32 || ty == Ity_I16 || ty == Ity_I8) { 5899ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int szB = 0; 5900ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg r_dst = lookupIRTemp(env, res); 5901ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HReg raddr = iselIntExpr_R(env, stmt->Ist.LLSC.addr); 5902ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (ty) { 5903ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Ity_I8: szB = 1; break; 5904b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov case Ity_I16: szB = 2; break; 5905ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Ity_I32: szB = 4; break; 5906ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: vassert(0); 5907ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5908b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov addInstr(env, mk_iMOVds_RR(hregARM_R4(), raddr)); 5909ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_LdrEX(szB)); 5910584369aa497a47058d868ea1330f92df8bc6c7c5Kenny Root addInstr(env, mk_iMOVds_RR(r_dst, hregARM_R2())); 5911584369aa497a47058d868ea1330f92df8bc6c7c5Kenny Root return; 5912b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } 5913b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (ty == Ity_I64) { 5914584369aa497a47058d868ea1330f92df8bc6c7c5Kenny Root HReg raddr = iselIntExpr_R(env, stmt->Ist.LLSC.addr); 5915b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov addInstr(env, mk_iMOVds_RR(hregARM_R4(), raddr)); 5916b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov addInstr(env, ARMInstr_LdrEX(8)); 5917b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov /* Result is in r3:r2. On a non-NEON capable CPU, we must 5918b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov move it into a result register pair. On a NEON capable 5919b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov CPU, the result register will be a 64 bit NEON 5920b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov register, so we must move it there instead. */ 5921663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng if (env->hwcaps & VEX_HWCAPS_ARM_NEON) { 5922b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov HReg dst = lookupIRTemp(env, res); 5923b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov addInstr(env, ARMInstr_VXferD(True, dst, hregARM_R3(), 5924b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov hregARM_R2())); 59250d91818fa30df681e42e17d1f853e4db276a6a34Evgeniy Stepanov } else { 5926b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov HReg r_dst_hi, r_dst_lo; 5927b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov lookupIRTemp64(&r_dst_hi, &r_dst_lo, env, res); 5928b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov addInstr(env, mk_iMOVds_RR(r_dst_lo, hregARM_R2())); 5929b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov addInstr(env, mk_iMOVds_RR(r_dst_hi, hregARM_R3())); 59300d91818fa30df681e42e17d1f853e4db276a6a34Evgeniy Stepanov } 5931ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return; 5932ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5933b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov /*NOTREACHED*/ 5934b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov vassert(0); 5935ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 5936ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* SC */ 5937ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IRType tyd = typeOfIRExpr(env->type_env, stmt->Ist.LLSC.storedata); 5938b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (tyd == Ity_I32 || tyd == Ity_I16 || tyd == Ity_I8) { 5939b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov Int szB = 0; 5940b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov HReg rD = iselIntExpr_R(env, stmt->Ist.LLSC.storedata); 5941b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov HReg rA = iselIntExpr_R(env, stmt->Ist.LLSC.addr); 5942ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (tyd) { 5943ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Ity_I8: szB = 1; break; 5944b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov case Ity_I16: szB = 2; break; 5945ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Ity_I32: szB = 4; break; 5946ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: vassert(0); 5947ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5948584369aa497a47058d868ea1330f92df8bc6c7c5Kenny Root addInstr(env, mk_iMOVds_RR(hregARM_R2(), rD)); 5949b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov addInstr(env, mk_iMOVds_RR(hregARM_R4(), rA)); 5950ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown addInstr(env, ARMInstr_StrEX(szB)); 5951b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } else { 5952b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov vassert(tyd == Ity_I64); 5953b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov /* This is really ugly. There is no is/is-not NEON 5954b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov decision akin to the case for LL, because iselInt64Expr 5955b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov fudges this for us, and always gets the result into two 5956b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov GPRs even if this means moving it from a NEON 5957b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov register. */ 5958b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov HReg rDhi, rDlo; 5959b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov iselInt64Expr(&rDhi, &rDlo, env, stmt->Ist.LLSC.storedata); 5960b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov HReg rA = iselIntExpr_R(env, stmt->Ist.LLSC.addr); 5961b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov addInstr(env, mk_iMOVds_RR(hregARM_R2(), rDlo)); 5962b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov addInstr(env, mk_iMOVds_RR(hregARM_R3(), rDhi)); 5963b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov addInstr(env, mk_iMOVds_RR(hregARM_R4(), rA)); 5964b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov addInstr(env, ARMInstr_StrEX(8)); 5965b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } 5966b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov /* now r0 is 1 if failed, 0 if success. Change to IR 5967b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov conventions (0 is fail, 1 is success). Also transfer 5968b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov result to r_res. */ 5969b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov IRTemp res = stmt->Ist.LLSC.result; 5970b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov IRType ty = typeOfIRTemp(env->type_env, res); 5971b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov HReg r_res = lookupIRTemp(env, res); 5972b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov ARMRI84* one = ARMRI84_I84(1,0); 5973b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov vassert(ty == Ity_I1); 5974b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov addInstr(env, ARMInstr_Alu(ARMalu_XOR, r_res, hregARM_R0(), one)); 5975b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov /* And be conservative -- mask off all but the lowest bit */ 5976b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov addInstr(env, ARMInstr_Alu(ARMalu_AND, r_res, r_res, one)); 5977b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov return; 5978ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5979ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 5980ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5981ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 5982ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* --------- MEM FENCE --------- */ 5983ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Ist_MBE: 5984ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (stmt->Ist.MBE.event) { 5985ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Imbe_Fence: 5986b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov addInstr(env, ARMInstr_MFence()); 5987b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov return; 5988b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov case Imbe_CancelReservation: 5989b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov addInstr(env, ARMInstr_CLREX()); 5990ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return; 5991ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: 5992ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 5993ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 5994ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 5995ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 5996ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* --------- INSTR MARK --------- */ 5997ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Doesn't generate any executable code ... */ 5998ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Ist_IMark: 5999ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return; 6000ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 6001ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* --------- NO-OP --------- */ 6002ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Ist_NoOp: 6003ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return; 6004ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 6005ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* --------- EXIT --------- */ 6006ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Ist_Exit: { 6007ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (stmt->Ist.Exit.dst->tag != Ico_U32) 6008ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vpanic("isel_arm: Ist_Exit: dst is not a 32-bit value"); 6009663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 6010663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng ARMCondCode cc = iselCondCode(env, stmt->Ist.Exit.guard); 6011663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng ARMAMode1* amR15T = ARMAMode1_RI(hregARM_R8(), 6012663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng stmt->Ist.Exit.offsIP); 6013663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 6014663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng /* Case: boring transfer to known address */ 6015663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng if (stmt->Ist.Exit.jk == Ijk_Boring 6016663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng || stmt->Ist.Exit.jk == Ijk_Call 6017663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng || stmt->Ist.Exit.jk == Ijk_Ret) { 6018663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng if (env->chainingAllowed) { 6019663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng /* .. almost always true .. */ 6020663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng /* Skip the event check at the dst if this is a forwards 6021663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng edge. */ 6022663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng Bool toFastEP 6023663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng = ((Addr32)stmt->Ist.Exit.dst->Ico.U32) > env->max_ga; 6024663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng if (0) vex_printf("%s", toFastEP ? "Y" : ","); 6025663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng addInstr(env, ARMInstr_XDirect(stmt->Ist.Exit.dst->Ico.U32, 6026663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng amR15T, cc, toFastEP)); 6027663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng } else { 6028663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng /* .. very occasionally .. */ 6029663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng /* We can't use chaining, so ask for an assisted transfer, 6030663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng as that's the only alternative that is allowable. */ 6031663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng HReg r = iselIntExpr_R(env, IRExpr_Const(stmt->Ist.Exit.dst)); 6032663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng addInstr(env, ARMInstr_XAssisted(r, amR15T, cc, Ijk_Boring)); 6033663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng } 6034663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng return; 6035663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng } 6036663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 6037663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng /* Case: assisted transfer to arbitrary address */ 6038663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng switch (stmt->Ist.Exit.jk) { 6039663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng /* Keep this list in sync with that in iselNext below */ 6040663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng case Ijk_ClientReq: 6041663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng case Ijk_NoDecode: 6042663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng case Ijk_NoRedir: 6043663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng case Ijk_Sys_syscall: 6044663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng case Ijk_TInval: 6045663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng { 6046663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng HReg r = iselIntExpr_R(env, IRExpr_Const(stmt->Ist.Exit.dst)); 6047663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng addInstr(env, ARMInstr_XAssisted(r, amR15T, cc, 6048663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng stmt->Ist.Exit.jk)); 6049663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng return; 6050663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng } 6051663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng default: 6052663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng break; 6053663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng } 6054663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 6055663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng /* Do we ever expect to see any other kind? */ 6056663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng goto stmt_fail; 6057ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 6058ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 6059ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: break; 6060ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 6061ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown stmt_fail: 6062ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ppIRStmt(stmt); 6063ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vpanic("iselStmt"); 6064ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 6065ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 6066ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 6067ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------*/ 6068ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- ISEL: Basic block terminators (Nexts) ---*/ 6069ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------*/ 6070ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 6071663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic void iselNext ( ISelEnv* env, 6072663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng IRExpr* next, IRJumpKind jk, Int offsIP ) 6073ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 6074ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (vex_traceflags & VEX_TRACE_VCODE) { 6075663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng vex_printf( "\n-- PUT(%d) = ", offsIP); 6076663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng ppIRExpr( next ); 6077663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng vex_printf( "; exit-"); 6078ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ppIRJumpKind(jk); 6079663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng vex_printf( "\n"); 6080663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng } 6081663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 6082663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng /* Case: boring transfer to known address */ 6083663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng if (next->tag == Iex_Const) { 6084663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng IRConst* cdst = next->Iex.Const.con; 6085663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng vassert(cdst->tag == Ico_U32); 6086663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng if (jk == Ijk_Boring || jk == Ijk_Call) { 6087663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng /* Boring transfer to known address */ 6088663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng ARMAMode1* amR15T = ARMAMode1_RI(hregARM_R8(), offsIP); 6089663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng if (env->chainingAllowed) { 6090663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng /* .. almost always true .. */ 6091663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng /* Skip the event check at the dst if this is a forwards 6092663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng edge. */ 6093663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng Bool toFastEP 6094663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng = ((Addr64)cdst->Ico.U32) > env->max_ga; 6095663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng if (0) vex_printf("%s", toFastEP ? "X" : "."); 6096663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng addInstr(env, ARMInstr_XDirect(cdst->Ico.U32, 6097663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng amR15T, ARMcc_AL, 6098663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng toFastEP)); 6099663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng } else { 6100663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng /* .. very occasionally .. */ 6101663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng /* We can't use chaining, so ask for an assisted transfer, 6102663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng as that's the only alternative that is allowable. */ 6103663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng HReg r = iselIntExpr_R(env, next); 6104663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng addInstr(env, ARMInstr_XAssisted(r, amR15T, ARMcc_AL, 6105663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng Ijk_Boring)); 6106663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng } 6107663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng return; 6108663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng } 6109663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng } 6110663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 6111663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng /* Case: call/return (==boring) transfer to any address */ 6112663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng switch (jk) { 6113663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng case Ijk_Boring: case Ijk_Ret: case Ijk_Call: { 6114663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng HReg r = iselIntExpr_R(env, next); 6115663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng ARMAMode1* amR15T = ARMAMode1_RI(hregARM_R8(), offsIP); 6116663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng if (env->chainingAllowed) { 6117663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng addInstr(env, ARMInstr_XIndir(r, amR15T, ARMcc_AL)); 6118663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng } else { 6119663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng addInstr(env, ARMInstr_XAssisted(r, amR15T, ARMcc_AL, 6120663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng Ijk_Boring)); 6121663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng } 6122663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng return; 6123663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng } 6124663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng default: 6125663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng break; 6126663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng } 6127663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 6128663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng /* Case: assisted transfer to arbitrary address */ 6129663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng switch (jk) { 6130663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng /* Keep this list in sync with that for Ist_Exit above */ 6131663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng case Ijk_ClientReq: 6132663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng case Ijk_NoDecode: 6133663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng case Ijk_NoRedir: 6134663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng case Ijk_Sys_syscall: 6135663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng { 6136663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng HReg r = iselIntExpr_R(env, next); 6137663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng ARMAMode1* amR15T = ARMAMode1_RI(hregARM_R8(), offsIP); 6138663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng addInstr(env, ARMInstr_XAssisted(r, amR15T, ARMcc_AL, jk)); 6139663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng return; 6140663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng } 6141663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng default: 6142663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng break; 6143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 6144663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 6145663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng vex_printf( "\n-- PUT(%d) = ", offsIP); 6146663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng ppIRExpr( next ); 6147663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng vex_printf( "; exit-"); 6148663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng ppIRJumpKind(jk); 6149663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng vex_printf( "\n"); 6150663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng vassert(0); // are we expecting any other kind? 6151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 6152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 6153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 6154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------*/ 6155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Insn selector top-level ---*/ 6156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------*/ 6157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 6158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Translate an entire SB to arm code. */ 6159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 6160663860b1408516d02ebfcb3a9999a134e6cfb223Ben ChengHInstrArray* iselSB_ARM ( IRSB* bb, 6161663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng VexArch arch_host, 6162663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng VexArchInfo* archinfo_host, 6163663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng VexAbiInfo* vbi/*UNUSED*/, 6164663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng Int offs_Host_EvC_Counter, 6165663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng Int offs_Host_EvC_FailAddr, 6166663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng Bool chainingAllowed, 6167663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng Bool addProfInc, 6168663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng Addr64 max_ga ) 6169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 6170663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng Int i, j; 6171663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng HReg hreg, hregHI; 6172663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng ISelEnv* env; 6173663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng UInt hwcaps_host = archinfo_host->hwcaps; 6174663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng ARMAMode1 *amCounter, *amFailAddr; 6175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 6176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* sanity ... */ 6177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vassert(arch_host == VexArchARM); 6178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 6179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* hwcaps should not change from one ISEL call to another. */ 6180663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng arm_hwcaps = hwcaps_host; // JRS 2012 Mar 31: FIXME (RM) 6181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 6182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Make up an initial environment to use. */ 6183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown env = LibVEX_Alloc(sizeof(ISelEnv)); 6184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown env->vreg_ctr = 0; 6185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 6186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Set up output code array. */ 6187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown env->code = newHInstrArray(); 6188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 6189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Copy BB's type env. */ 6190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown env->type_env = bb->tyenv; 6191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 6192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Make up an IRTemp -> virtual HReg mapping. This doesn't 6193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown change as we go along. */ 6194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown env->n_vregmap = bb->tyenv->types_used; 6195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown env->vregmap = LibVEX_Alloc(env->n_vregmap * sizeof(HReg)); 6196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown env->vregmapHI = LibVEX_Alloc(env->n_vregmap * sizeof(HReg)); 6197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 6198663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng /* and finally ... */ 6199663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng env->chainingAllowed = chainingAllowed; 6200663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng env->hwcaps = hwcaps_host; 6201663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng env->max_ga = max_ga; 6202663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 6203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* For each IR temporary, allocate a suitably-kinded virtual 6204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown register. */ 6205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown j = 0; 6206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (i = 0; i < env->n_vregmap; i++) { 6207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown hregHI = hreg = INVALID_HREG; 6208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (bb->tyenv->types[i]) { 6209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Ity_I1: 6210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Ity_I8: 6211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Ity_I16: 6212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Ity_I32: hreg = mkHReg(j++, HRcInt32, True); break; 6213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Ity_I64: 6214663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng if (hwcaps_host & VEX_HWCAPS_ARM_NEON) { 6215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown hreg = mkHReg(j++, HRcFlt64, True); 6216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 6217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown hregHI = mkHReg(j++, HRcInt32, True); 6218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown hreg = mkHReg(j++, HRcInt32, True); 6219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 6220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 6221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Ity_F32: hreg = mkHReg(j++, HRcFlt32, True); break; 6222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case Ity_F64: hreg = mkHReg(j++, HRcFlt64, True); break; 6223b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov case Ity_V128: hreg = mkHReg(j++, HRcVec128, True); break; 6224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: ppIRType(bb->tyenv->types[i]); 6225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vpanic("iselBB: IRTemp type"); 6226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 6227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown env->vregmap[i] = hreg; 6228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown env->vregmapHI[i] = hregHI; 6229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 6230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown env->vreg_ctr = j; 6231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 6232663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng /* The very first instruction must be an event check. */ 6233663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng amCounter = ARMAMode1_RI(hregARM_R8(), offs_Host_EvC_Counter); 6234663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng amFailAddr = ARMAMode1_RI(hregARM_R8(), offs_Host_EvC_FailAddr); 6235663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng addInstr(env, ARMInstr_EvCheck(amCounter, amFailAddr)); 6236663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 6237663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng /* Possibly a block counter increment (for profiling). At this 6238663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng point we don't know the address of the counter, so just pretend 6239663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng it is zero. It will have to be patched later, but before this 6240663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng translation is used, by a call to LibVEX_patchProfCtr. */ 6241663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng if (addProfInc) { 6242663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng addInstr(env, ARMInstr_ProfInc()); 6243663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng } 6244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 6245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Ok, finally we can iterate over the statements. */ 6246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (i = 0; i < bb->stmts_used; i++) 6247663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng iselStmt(env, bb->stmts[i]); 6248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 6249663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng iselNext(env, bb->next, bb->jumpkind, bb->offsIP); 6250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 6251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* record the number of vregs we used. */ 6252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown env->code->n_vregs = env->vreg_ctr; 6253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return env->code; 6254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 6255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 6256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 6257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------------*/ 6258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- end host_arm_isel.c ---*/ 6259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---------------------------------------------------------------*/ 6260