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