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