1ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/
3ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- begin                                       guest_arm_toIR.c ---*/
4ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/
5ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*
7ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   This file is part of Valgrind, a dynamic binary instrumentation
8ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   framework.
9ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   Copyright (C) 2004-2012 OpenWorks LLP
11ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      info@open-works.net
12ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   NEON support is
14663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   Copyright (C) 2010-2012 Samsung Electronics
15ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   contributed by Dmitry Zhurikhin <zhur@ispras.ru>
16ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              and Kirill Batuzov <batuzovk@ispras.ru>
17ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
18ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   This program is free software; you can redistribute it and/or
19ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   modify it under the terms of the GNU General Public License as
20ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   published by the Free Software Foundation; either version 2 of the
21ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   License, or (at your option) any later version.
22ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
23ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   This program is distributed in the hope that it will be useful, but
24ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   WITHOUT ANY WARRANTY; without even the implied warranty of
25ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
26ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   General Public License for more details.
27ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
28ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   You should have received a copy of the GNU General Public License
29ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   along with this program; if not, write to the Free Software
30ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
31ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   02110-1301, USA.
32ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
33ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   The GNU General Public License is contained in the file COPYING.
34ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
35ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
36ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* XXXX thumb to check:
37ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   that all cases where putIRegT writes r15, we generate a jump.
38ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
39ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   All uses of newTemp assign to an IRTemp and not a UInt
40ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
41ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   For all thumb loads and stores, including VFP ones, new-ITSTATE is
42ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   backed out before the memory op, and restored afterwards.  This
43ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   needs to happen even after we go uncond.  (and for sure it doesn't
44ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   happen for VFP loads/stores right now).
45ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
46ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VFP on thumb: check that we exclude all r13/r15 cases that we
47ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   should.
48ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
49ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   XXXX thumb to do: improve the ITSTATE-zeroing optimisation by
50ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   taking into account the number of insns guarded by an IT.
51ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
52ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   remove the nasty hack, in the spechelper, of looking for Or32(...,
53ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   0xE0) in as the first arg to armg_calculate_condition, and instead
54ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   use Slice44 as specified in comments in the spechelper.
55ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
56ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   add specialisations for armg_calculate_flag_c and _v, as they
57ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   are moderately often needed in Thumb code.
58ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
59ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Correctness: ITSTATE handling in Thumb SVCs is wrong.
60ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
61ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Correctness (obscure): in m_transtab, when invalidating code
62ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   address ranges, invalidate up to 18 bytes after the end of the
63ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   range.  This is because the ITSTATE optimisation at the top of
64ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   _THUMB_WRK below analyses up to 18 bytes before the start of any
65ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   given instruction, and so might depend on the invalidated area.
66ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
67ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
68ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Limitations, etc
69ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
70ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   - pretty dodgy exception semantics for {LD,ST}Mxx, no doubt
71ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
72ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   - SWP: the restart jump back is Ijk_Boring; it should be
73ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     Ijk_NoRedir but that's expensive.  See comments on casLE() in
74ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     guest_x86_toIR.c.
75ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
76ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
77ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* "Special" instructions.
78ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
79ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   This instruction decoder can decode four special instructions
80ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   which mean nothing natively (are no-ops as far as regs/mem are
81ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   concerned) but have meaning for supporting Valgrind.  A special
82ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   instruction is flagged by a 16-byte preamble:
83ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
84ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      E1A0C1EC E1A0C6EC E1A0CEEC E1A0C9EC
85ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      (mov r12, r12, ROR #3;   mov r12, r12, ROR #13;
86ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       mov r12, r12, ROR #29;  mov r12, r12, ROR #19)
87ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
88ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Following that, one of the following 3 are allowed
89ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   (standard interpretation in parentheses):
90ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
91ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      E18AA00A (orr r10,r10,r10)   R3 = client_request ( R4 )
92ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      E18BB00B (orr r11,r11,r11)   R3 = guest_NRADDR
93ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      E18CC00C (orr r12,r12,r12)   branch-and-link-to-noredir R4
94ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
95ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Any other bytes following the 16-byte preamble are illegal and
96ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   constitute a failure in instruction decoding.  This all assumes
97ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   that the preamble will never occur except in specific code
98ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   fragments designed for Valgrind to catch.
99ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Translates ARM(v5) code to IR. */
102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "libvex_basictypes.h"
104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "libvex_ir.h"
105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "libvex.h"
106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "libvex_guest_arm.h"
107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "main_util.h"
109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "main_globals.h"
110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "guest_generic_bb_to_IR.h"
111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "guest_arm_defs.h"
112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Globals                                              ---*/
116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* These are set at the start of the translation of a instruction, so
119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   that we don't have to pass them around endlessly.  CONST means does
120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   not change during translation of the instruction.
121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* CONST: is the host bigendian?  This has to do with float vs double
124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   register accesses on VFP, but it's complex and not properly thought
125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   out. */
126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool host_is_bigendian;
127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* CONST: The guest address for the instruction currently being
129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   translated.  This is the real, "decoded" address (not subject
130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   to the CPSR.T kludge). */
131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Addr32 guest_R15_curr_instr_notENC;
132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* CONST, FOR ASSERTIONS ONLY.  Indicates whether currently processed
134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   insn is Thumb (True) or ARM (False). */
135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool __curr_is_Thumb;
136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* MOD: The IRSB* into which we're generating code. */
138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRSB* irsb;
139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* These are to do with handling writes to r15.  They are initially
141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   set at the start of disInstr_ARM_WRK to indicate no update,
142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   possibly updated during the routine, and examined again at the end.
143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   If they have been set to indicate a r15 update then a jump is
144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   generated.  Note, "explicit" jumps (b, bx, etc) are generated
145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   directly, not using this mechanism -- this is intended to handle
146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   the implicit-style jumps resulting from (eg) assigning to r15 as
147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   the result of insns we wouldn't normally consider branchy. */
148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* MOD.  Initially False; set to True iff abovementioned handling is
150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   required. */
151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool r15written;
152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* MOD.  Initially IRTemp_INVALID.  If the r15 branch to be generated
154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   is conditional, this holds the gating IRTemp :: Ity_I32.  If the
155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   branch to be generated is unconditional, this remains
156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp_INVALID. */
157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRTemp r15guard; /* :: Ity_I32, 0 or 1 */
158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* MOD.  Initially Ijk_Boring.  If an r15 branch is to be generated,
160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   this holds the jump kind. */
161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRTemp r15kind;
162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Debugging output                                     ---*/
166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define DIP(format, args...)           \
169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (vex_traceflags & VEX_TRACE_FE)  \
170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vex_printf(format, ## args)
171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define DIS(buf, format, args...)      \
173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (vex_traceflags & VEX_TRACE_FE)  \
174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vex_sprintf(buf, format, ## args)
175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define ASSERT_IS_THUMB \
177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   do { vassert(__curr_is_Thumb); } while (0)
178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define ASSERT_IS_ARM \
180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   do { vassert(! __curr_is_Thumb); } while (0)
181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Helper bits and pieces for deconstructing the        ---*/
185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- arm insn stream.                                     ---*/
186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Do a little-endian load of a 32-bit word, regardless of the
189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   endianness of the underlying host. */
190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic inline UInt getUIntLittleEndianly ( UChar* p )
191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt w = 0;
193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   w = (w << 8) | p[3];
194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   w = (w << 8) | p[2];
195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   w = (w << 8) | p[1];
196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   w = (w << 8) | p[0];
197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return w;
198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Do a little-endian load of a 16-bit word, regardless of the
201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   endianness of the underlying host. */
202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic inline UShort getUShortLittleEndianly ( UChar* p )
203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UShort w = 0;
205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   w = (w << 8) | p[1];
206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   w = (w << 8) | p[0];
207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return w;
208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic UInt ROR32 ( UInt x, UInt sh ) {
211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(sh >= 0 && sh < 32);
212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (sh == 0)
213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return x;
214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   else
215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return (x << (32-sh)) | (x >> sh);
216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Int popcount32 ( UInt x )
219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int res = 0, i;
221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (i = 0; i < 32; i++) {
222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      res += (x & 1);
223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      x >>= 1;
224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return res;
226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic UInt setbit32 ( UInt x, Int ix, UInt b )
229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt mask = 1 << ix;
231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   x &= ~mask;
232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   x |= ((b << ix) & mask);
233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return x;
234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define BITS2(_b1,_b0) \
237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   (((_b1) << 1) | (_b0))
238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define BITS3(_b2,_b1,_b0)                      \
240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  (((_b2) << 2) | ((_b1) << 1) | (_b0))
241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define BITS4(_b3,_b2,_b1,_b0) \
243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   (((_b3) << 3) | ((_b2) << 2) | ((_b1) << 1) | (_b0))
244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define BITS8(_b7,_b6,_b5,_b4,_b3,_b2,_b1,_b0)  \
246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ((BITS4((_b7),(_b6),(_b5),(_b4)) << 4) \
247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    | BITS4((_b3),(_b2),(_b1),(_b0)))
248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define BITS5(_b4,_b3,_b2,_b1,_b0)  \
250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   (BITS8(0,0,0,(_b4),(_b3),(_b2),(_b1),(_b0)))
251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define BITS6(_b5,_b4,_b3,_b2,_b1,_b0)  \
252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   (BITS8(0,0,(_b5),(_b4),(_b3),(_b2),(_b1),(_b0)))
253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define BITS7(_b6,_b5,_b4,_b3,_b2,_b1,_b0)  \
254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   (BITS8(0,(_b6),(_b5),(_b4),(_b3),(_b2),(_b1),(_b0)))
255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define BITS9(_b8,_b7,_b6,_b5,_b4,_b3,_b2,_b1,_b0)      \
257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   (((_b8) << 8) \
258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    | BITS8((_b7),(_b6),(_b5),(_b4),(_b3),(_b2),(_b1),(_b0)))
259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define BITS10(_b9,_b8,_b7,_b6,_b5,_b4,_b3,_b2,_b1,_b0)  \
261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   (((_b9) << 9) | ((_b8) << 8)                                \
262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    | BITS8((_b7),(_b6),(_b5),(_b4),(_b3),(_b2),(_b1),(_b0)))
263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* produces _uint[_bMax:_bMin] */
265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define SLICE_UInt(_uint,_bMax,_bMin) \
266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   (( ((UInt)(_uint)) >> (_bMin)) \
267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    & (UInt)((1ULL << ((_bMax) - (_bMin) + 1)) - 1ULL))
268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Helper bits and pieces for creating IR fragments.    ---*/
272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRExpr* mkU64 ( ULong i )
275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return IRExpr_Const(IRConst_U64(i));
277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRExpr* mkU32 ( UInt i )
280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return IRExpr_Const(IRConst_U32(i));
282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRExpr* mkU8 ( UInt i )
285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(i < 256);
287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return IRExpr_Const(IRConst_U8( (UChar)i ));
288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRExpr* mkexpr ( IRTemp tmp )
291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return IRExpr_RdTmp(tmp);
293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRExpr* unop ( IROp op, IRExpr* a )
296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return IRExpr_Unop(op, a);
298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRExpr* binop ( IROp op, IRExpr* a1, IRExpr* a2 )
301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return IRExpr_Binop(op, a1, a2);
303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRExpr* triop ( IROp op, IRExpr* a1, IRExpr* a2, IRExpr* a3 )
306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return IRExpr_Triop(op, a1, a2, a3);
308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRExpr* loadLE ( IRType ty, IRExpr* addr )
311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return IRExpr_Load(Iend_LE, ty, addr);
313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Add a statement to the list held by "irbb". */
316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void stmt ( IRStmt* st )
317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   addStmtToIRSB( irsb, st );
319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void assign ( IRTemp dst, IRExpr* e )
322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   stmt( IRStmt_WrTmp(dst, e) );
324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void storeLE ( IRExpr* addr, IRExpr* data )
327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   stmt( IRStmt_Store(Iend_LE, addr, data) );
329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Generate a new temporary of the given type. */
332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRTemp newTemp ( IRType ty )
333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(isPlausibleIRType(ty));
335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return newIRTemp( irsb->tyenv, ty );
336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Produces a value in 0 .. 3, which is encoded as per the type
339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRRoundingMode. */
340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRExpr* /* :: Ity_I32 */ get_FAKE_roundingmode ( void )
341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return mkU32(Irrm_NEAREST);
343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Generate an expression for SRC rotated right by ROT. */
346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRExpr* genROR32( IRTemp src, Int rot )
347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(rot >= 0 && rot < 32);
349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (rot == 0)
350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return mkexpr(src);
351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return
352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      binop(Iop_Or32,
353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            binop(Iop_Shl32, mkexpr(src), mkU8(32 - rot)),
354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            binop(Iop_Shr32, mkexpr(src), mkU8(rot)));
355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRExpr* mkU128 ( ULong i )
358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return binop(Iop_64HLtoV128, mkU64(i), mkU64(i));
360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Generate a 4-aligned version of the given expression if
363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   the given condition is true.  Else return it unchanged. */
364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRExpr* align4if ( IRExpr* e, Bool b )
365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (b)
367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return binop(Iop_And32, e, mkU32(~3));
368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   else
369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return e;
370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Helpers for accessing guest registers.               ---*/
375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define OFFB_R0       offsetof(VexGuestARMState,guest_R0)
378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define OFFB_R1       offsetof(VexGuestARMState,guest_R1)
379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define OFFB_R2       offsetof(VexGuestARMState,guest_R2)
380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define OFFB_R3       offsetof(VexGuestARMState,guest_R3)
381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define OFFB_R4       offsetof(VexGuestARMState,guest_R4)
382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define OFFB_R5       offsetof(VexGuestARMState,guest_R5)
383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define OFFB_R6       offsetof(VexGuestARMState,guest_R6)
384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define OFFB_R7       offsetof(VexGuestARMState,guest_R7)
385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define OFFB_R8       offsetof(VexGuestARMState,guest_R8)
386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define OFFB_R9       offsetof(VexGuestARMState,guest_R9)
387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define OFFB_R10      offsetof(VexGuestARMState,guest_R10)
388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define OFFB_R11      offsetof(VexGuestARMState,guest_R11)
389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define OFFB_R12      offsetof(VexGuestARMState,guest_R12)
390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define OFFB_R13      offsetof(VexGuestARMState,guest_R13)
391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define OFFB_R14      offsetof(VexGuestARMState,guest_R14)
392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define OFFB_R15T     offsetof(VexGuestARMState,guest_R15T)
393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define OFFB_CC_OP    offsetof(VexGuestARMState,guest_CC_OP)
395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define OFFB_CC_DEP1  offsetof(VexGuestARMState,guest_CC_DEP1)
396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define OFFB_CC_DEP2  offsetof(VexGuestARMState,guest_CC_DEP2)
397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define OFFB_CC_NDEP  offsetof(VexGuestARMState,guest_CC_NDEP)
398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define OFFB_NRADDR   offsetof(VexGuestARMState,guest_NRADDR)
399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define OFFB_D0       offsetof(VexGuestARMState,guest_D0)
401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define OFFB_D1       offsetof(VexGuestARMState,guest_D1)
402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define OFFB_D2       offsetof(VexGuestARMState,guest_D2)
403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define OFFB_D3       offsetof(VexGuestARMState,guest_D3)
404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define OFFB_D4       offsetof(VexGuestARMState,guest_D4)
405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define OFFB_D5       offsetof(VexGuestARMState,guest_D5)
406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define OFFB_D6       offsetof(VexGuestARMState,guest_D6)
407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define OFFB_D7       offsetof(VexGuestARMState,guest_D7)
408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define OFFB_D8       offsetof(VexGuestARMState,guest_D8)
409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define OFFB_D9       offsetof(VexGuestARMState,guest_D9)
410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define OFFB_D10      offsetof(VexGuestARMState,guest_D10)
411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define OFFB_D11      offsetof(VexGuestARMState,guest_D11)
412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define OFFB_D12      offsetof(VexGuestARMState,guest_D12)
413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define OFFB_D13      offsetof(VexGuestARMState,guest_D13)
414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define OFFB_D14      offsetof(VexGuestARMState,guest_D14)
415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define OFFB_D15      offsetof(VexGuestARMState,guest_D15)
416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define OFFB_D16      offsetof(VexGuestARMState,guest_D16)
417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define OFFB_D17      offsetof(VexGuestARMState,guest_D17)
418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define OFFB_D18      offsetof(VexGuestARMState,guest_D18)
419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define OFFB_D19      offsetof(VexGuestARMState,guest_D19)
420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define OFFB_D20      offsetof(VexGuestARMState,guest_D20)
421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define OFFB_D21      offsetof(VexGuestARMState,guest_D21)
422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define OFFB_D22      offsetof(VexGuestARMState,guest_D22)
423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define OFFB_D23      offsetof(VexGuestARMState,guest_D23)
424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define OFFB_D24      offsetof(VexGuestARMState,guest_D24)
425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define OFFB_D25      offsetof(VexGuestARMState,guest_D25)
426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define OFFB_D26      offsetof(VexGuestARMState,guest_D26)
427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define OFFB_D27      offsetof(VexGuestARMState,guest_D27)
428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define OFFB_D28      offsetof(VexGuestARMState,guest_D28)
429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define OFFB_D29      offsetof(VexGuestARMState,guest_D29)
430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define OFFB_D30      offsetof(VexGuestARMState,guest_D30)
431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define OFFB_D31      offsetof(VexGuestARMState,guest_D31)
432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define OFFB_FPSCR    offsetof(VexGuestARMState,guest_FPSCR)
434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define OFFB_TPIDRURO offsetof(VexGuestARMState,guest_TPIDRURO)
435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define OFFB_ITSTATE  offsetof(VexGuestARMState,guest_ITSTATE)
436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define OFFB_QFLAG32  offsetof(VexGuestARMState,guest_QFLAG32)
437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define OFFB_GEFLAG0  offsetof(VexGuestARMState,guest_GEFLAG0)
438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define OFFB_GEFLAG1  offsetof(VexGuestARMState,guest_GEFLAG1)
439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define OFFB_GEFLAG2  offsetof(VexGuestARMState,guest_GEFLAG2)
440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define OFFB_GEFLAG3  offsetof(VexGuestARMState,guest_GEFLAG3)
441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* ---------------- Integer registers ---------------- */
444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Int integerGuestRegOffset ( UInt iregNo )
446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Do we care about endianness here?  We do if sub-parts of integer
448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      registers are accessed, but I don't think that ever happens on
449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ARM. */
450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (iregNo) {
451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0:  return OFFB_R0;
452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 1:  return OFFB_R1;
453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 2:  return OFFB_R2;
454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 3:  return OFFB_R3;
455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 4:  return OFFB_R4;
456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 5:  return OFFB_R5;
457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 6:  return OFFB_R6;
458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 7:  return OFFB_R7;
459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 8:  return OFFB_R8;
460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 9:  return OFFB_R9;
461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 10: return OFFB_R10;
462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 11: return OFFB_R11;
463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 12: return OFFB_R12;
464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 13: return OFFB_R13;
465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 14: return OFFB_R14;
466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 15: return OFFB_R15T;
467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default: vassert(0);
468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Plain ("low level") read from a reg; no +8 offset magic for r15. */
472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRExpr* llGetIReg ( UInt iregNo )
473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(iregNo < 16);
475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return IRExpr_Get( integerGuestRegOffset(iregNo), Ity_I32 );
476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Architected read from a reg in ARM mode.  This automagically adds 8
479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   to all reads of r15. */
480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRExpr* getIRegA ( UInt iregNo )
481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRExpr* e;
483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ASSERT_IS_ARM;
484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(iregNo < 16);
485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (iregNo == 15) {
486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* If asked for r15, don't read the guest state value, as that
487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         may not be up to date in the case where loop unrolling has
488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         happened, because the first insn's write to the block is
489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         omitted; hence in the 2nd and subsequent unrollings we don't
490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         have a correct value in guest r15.  Instead produce the
491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         constant that we know would be produced at this point. */
492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert(0 == (guest_R15_curr_instr_notENC & 3));
493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      e = mkU32(guest_R15_curr_instr_notENC + 8);
494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      e = IRExpr_Get( integerGuestRegOffset(iregNo), Ity_I32 );
496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return e;
498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Architected read from a reg in Thumb mode.  This automagically adds
501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   4 to all reads of r15. */
502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRExpr* getIRegT ( UInt iregNo )
503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRExpr* e;
505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ASSERT_IS_THUMB;
506ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(iregNo < 16);
507ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (iregNo == 15) {
508ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Ditto comment in getIReg. */
509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert(0 == (guest_R15_curr_instr_notENC & 1));
510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      e = mkU32(guest_R15_curr_instr_notENC + 4);
511ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
512ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      e = IRExpr_Get( integerGuestRegOffset(iregNo), Ity_I32 );
513ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
514ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return e;
515ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
516ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
517ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Plain ("low level") write to a reg; no jump or alignment magic for
518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   r15. */
519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void llPutIReg ( UInt iregNo, IRExpr* e )
520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
521ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(iregNo < 16);
522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I32);
523ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   stmt( IRStmt_Put(integerGuestRegOffset(iregNo), e) );
524ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
525ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
526ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Architected write to an integer register in ARM mode.  If it is to
527ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   r15, record info so at the end of this insn's translation, a branch
528ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   to it can be made.  Also handles conditional writes to the
529ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   register: if guardT == IRTemp_INVALID then the write is
530ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   unconditional.  If writing r15, also 4-align it. */
531ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void putIRegA ( UInt       iregNo,
532ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       IRExpr*    e,
533ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       IRTemp     guardT /* :: Ity_I32, 0 or 1 */,
534ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       IRJumpKind jk /* if a jump is generated */ )
535ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
536ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* if writing r15, force e to be 4-aligned. */
537ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // INTERWORKING FIXME.  this needs to be relaxed so that
538ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // puts caused by LDMxx which load r15 interwork right.
539ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // but is no aligned too relaxed?
540ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //if (iregNo == 15)
541ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //   e = binop(Iop_And32, e, mkU32(~3));
542ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ASSERT_IS_ARM;
543ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* So, generate either an unconditional or a conditional write to
544ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      the reg. */
545ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (guardT == IRTemp_INVALID) {
546ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* unconditional write */
547ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      llPutIReg( iregNo, e );
548ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
549ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      llPutIReg( iregNo,
550ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 IRExpr_Mux0X( unop(Iop_32to8, mkexpr(guardT)),
551ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               llGetIReg(iregNo),
552ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               e ));
553ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
554ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (iregNo == 15) {
555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // assert against competing r15 updates.  Shouldn't
556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // happen; should be ruled out by the instr matching
557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // logic.
558ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert(r15written == False);
559ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert(r15guard   == IRTemp_INVALID);
560ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert(r15kind    == Ijk_Boring);
561ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      r15written = True;
562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      r15guard   = guardT;
563ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      r15kind    = jk;
564ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
565ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
566ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
567ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
568ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Architected write to an integer register in Thumb mode.  Writes to
569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   r15 are not allowed.  Handles conditional writes to the register:
570ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if guardT == IRTemp_INVALID then the write is unconditional. */
571ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void putIRegT ( UInt       iregNo,
572ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       IRExpr*    e,
573ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       IRTemp     guardT /* :: Ity_I32, 0 or 1 */ )
574ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* So, generate either an unconditional or a conditional write to
576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      the reg. */
577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ASSERT_IS_THUMB;
578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(iregNo >= 0 && iregNo <= 14);
579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (guardT == IRTemp_INVALID) {
580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* unconditional write */
581ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      llPutIReg( iregNo, e );
582ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      llPutIReg( iregNo,
584ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 IRExpr_Mux0X( unop(Iop_32to8, mkexpr(guardT)),
585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               llGetIReg(iregNo),
586ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               e ));
587ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Thumb16 and Thumb32 only.
592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Returns true if reg is 13 or 15.  Implements the BadReg
593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   predicate in the ARM ARM. */
594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool isBadRegT ( UInt r )
595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(r <= 15);
597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ASSERT_IS_THUMB;
598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return r == 13 || r == 15;
599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
602ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* ---------------- Double registers ---------------- */
603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Int doubleGuestRegOffset ( UInt dregNo )
605ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Do we care about endianness here?  Probably do if we ever get
607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      into the situation of dealing with the single-precision VFP
608ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      registers. */
609ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (dregNo) {
610ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0:  return OFFB_D0;
611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 1:  return OFFB_D1;
612ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 2:  return OFFB_D2;
613ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 3:  return OFFB_D3;
614ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 4:  return OFFB_D4;
615ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 5:  return OFFB_D5;
616ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 6:  return OFFB_D6;
617ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 7:  return OFFB_D7;
618ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 8:  return OFFB_D8;
619ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 9:  return OFFB_D9;
620ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 10: return OFFB_D10;
621ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 11: return OFFB_D11;
622ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 12: return OFFB_D12;
623ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 13: return OFFB_D13;
624ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 14: return OFFB_D14;
625ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 15: return OFFB_D15;
626ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 16: return OFFB_D16;
627ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 17: return OFFB_D17;
628ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 18: return OFFB_D18;
629ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 19: return OFFB_D19;
630ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 20: return OFFB_D20;
631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 21: return OFFB_D21;
632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 22: return OFFB_D22;
633ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 23: return OFFB_D23;
634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 24: return OFFB_D24;
635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 25: return OFFB_D25;
636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 26: return OFFB_D26;
637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 27: return OFFB_D27;
638ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 28: return OFFB_D28;
639ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 29: return OFFB_D29;
640ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 30: return OFFB_D30;
641ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 31: return OFFB_D31;
642ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default: vassert(0);
643ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
644ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
645ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
646ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Plain ("low level") read from a VFP Dreg. */
647ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRExpr* llGetDReg ( UInt dregNo )
648ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
649ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(dregNo < 32);
650ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return IRExpr_Get( doubleGuestRegOffset(dregNo), Ity_F64 );
651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
652ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
653ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Architected read from a VFP Dreg. */
654ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRExpr* getDReg ( UInt dregNo ) {
655ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return llGetDReg( dregNo );
656ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
657ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
658ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Plain ("low level") write to a VFP Dreg. */
659ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void llPutDReg ( UInt dregNo, IRExpr* e )
660ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
661ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(dregNo < 32);
662ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_F64);
663ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   stmt( IRStmt_Put(doubleGuestRegOffset(dregNo), e) );
664ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
665ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
666ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Architected write to a VFP Dreg.  Handles conditional writes to the
667ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   register: if guardT == IRTemp_INVALID then the write is
668ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   unconditional. */
669ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void putDReg ( UInt    dregNo,
670ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      IRExpr* e,
671ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      IRTemp  guardT /* :: Ity_I32, 0 or 1 */)
672ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
673ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* So, generate either an unconditional or a conditional write to
674ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      the reg. */
675ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (guardT == IRTemp_INVALID) {
676ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* unconditional write */
677ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      llPutDReg( dregNo, e );
678ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
679ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      llPutDReg( dregNo,
680ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 IRExpr_Mux0X( unop(Iop_32to8, mkexpr(guardT)),
681ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               llGetDReg(dregNo),
682ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               e ));
683ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
684ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
685ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
686ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* And now exactly the same stuff all over again, but this time
687ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   taking/returning I64 rather than F64, to support 64-bit Neon
688ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ops. */
689ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
690ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Plain ("low level") read from a Neon Integer Dreg. */
691ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRExpr* llGetDRegI64 ( UInt dregNo )
692ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
693ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(dregNo < 32);
694ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return IRExpr_Get( doubleGuestRegOffset(dregNo), Ity_I64 );
695ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
696ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
697ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Architected read from a Neon Integer Dreg. */
698ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRExpr* getDRegI64 ( UInt dregNo ) {
699ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return llGetDRegI64( dregNo );
700ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
701ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
702ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Plain ("low level") write to a Neon Integer Dreg. */
703ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void llPutDRegI64 ( UInt dregNo, IRExpr* e )
704ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
705ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(dregNo < 32);
706ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I64);
707ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   stmt( IRStmt_Put(doubleGuestRegOffset(dregNo), e) );
708ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
709ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
710ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Architected write to a Neon Integer Dreg.  Handles conditional
711ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   writes to the register: if guardT == IRTemp_INVALID then the write
712ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   is unconditional. */
713ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void putDRegI64 ( UInt    dregNo,
714ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         IRExpr* e,
715ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         IRTemp  guardT /* :: Ity_I32, 0 or 1 */)
716ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
717ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* So, generate either an unconditional or a conditional write to
718ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      the reg. */
719ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (guardT == IRTemp_INVALID) {
720ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* unconditional write */
721ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      llPutDRegI64( dregNo, e );
722ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
723ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      llPutDRegI64( dregNo,
724ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    IRExpr_Mux0X( unop(Iop_32to8, mkexpr(guardT)),
725ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                  llGetDRegI64(dregNo),
726ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                  e ));
727ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
728ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
729ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
730ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* ---------------- Quad registers ---------------- */
731ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
732ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Int quadGuestRegOffset ( UInt qregNo )
733ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
734ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Do we care about endianness here?  Probably do if we ever get
735ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      into the situation of dealing with the 64 bit Neon registers. */
736ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (qregNo) {
737ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0:  return OFFB_D0;
738ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 1:  return OFFB_D2;
739ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 2:  return OFFB_D4;
740ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 3:  return OFFB_D6;
741ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 4:  return OFFB_D8;
742ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 5:  return OFFB_D10;
743ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 6:  return OFFB_D12;
744ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 7:  return OFFB_D14;
745ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 8:  return OFFB_D16;
746ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 9:  return OFFB_D18;
747ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 10: return OFFB_D20;
748ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 11: return OFFB_D22;
749ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 12: return OFFB_D24;
750ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 13: return OFFB_D26;
751ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 14: return OFFB_D28;
752ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 15: return OFFB_D30;
753ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default: vassert(0);
754ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
755ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
756ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
757ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Plain ("low level") read from a Neon Qreg. */
758ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRExpr* llGetQReg ( UInt qregNo )
759ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
760ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(qregNo < 16);
761ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return IRExpr_Get( quadGuestRegOffset(qregNo), Ity_V128 );
762ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
763ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
764ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Architected read from a Neon Qreg. */
765ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRExpr* getQReg ( UInt qregNo ) {
766ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return llGetQReg( qregNo );
767ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
768ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
769ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Plain ("low level") write to a Neon Qreg. */
770ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void llPutQReg ( UInt qregNo, IRExpr* e )
771ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
772ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(qregNo < 16);
773ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_V128);
774ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   stmt( IRStmt_Put(quadGuestRegOffset(qregNo), e) );
775ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
776ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
777ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Architected write to a Neon Qreg.  Handles conditional writes to the
778ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   register: if guardT == IRTemp_INVALID then the write is
779ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   unconditional. */
780ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void putQReg ( UInt    qregNo,
781ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      IRExpr* e,
782ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      IRTemp  guardT /* :: Ity_I32, 0 or 1 */)
783ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
784ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* So, generate either an unconditional or a conditional write to
785ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      the reg. */
786ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (guardT == IRTemp_INVALID) {
787ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* unconditional write */
788ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      llPutQReg( qregNo, e );
789ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
790ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      llPutQReg( qregNo,
791ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 IRExpr_Mux0X( unop(Iop_32to8, mkexpr(guardT)),
792ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               llGetQReg(qregNo),
793ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               e ));
794ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
795ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
796ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
797ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
798ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* ---------------- Float registers ---------------- */
799ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
800ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Int floatGuestRegOffset ( UInt fregNo )
801ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
802ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Start with the offset of the containing double, and then correct
803ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      for endianness.  Actually this is completely bogus and needs
804ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      careful thought. */
805ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int off;
806ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(fregNo < 32);
807ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   off = doubleGuestRegOffset(fregNo >> 1);
808ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (host_is_bigendian) {
809ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert(0);
810ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
811ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (fregNo & 1)
812ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         off += 4;
813ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
814ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return off;
815ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
816ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
817ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Plain ("low level") read from a VFP Freg. */
818ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRExpr* llGetFReg ( UInt fregNo )
819ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
820ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(fregNo < 32);
821ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return IRExpr_Get( floatGuestRegOffset(fregNo), Ity_F32 );
822ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
823ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
824ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Architected read from a VFP Freg. */
825ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRExpr* getFReg ( UInt fregNo ) {
826ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return llGetFReg( fregNo );
827ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
828ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
829ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Plain ("low level") write to a VFP Freg. */
830ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void llPutFReg ( UInt fregNo, IRExpr* e )
831ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
832ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(fregNo < 32);
833ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_F32);
834ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   stmt( IRStmt_Put(floatGuestRegOffset(fregNo), e) );
835ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
836ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
837ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Architected write to a VFP Freg.  Handles conditional writes to the
838ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   register: if guardT == IRTemp_INVALID then the write is
839ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   unconditional. */
840ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void putFReg ( UInt    fregNo,
841ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      IRExpr* e,
842ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      IRTemp  guardT /* :: Ity_I32, 0 or 1 */)
843ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
844ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* So, generate either an unconditional or a conditional write to
845ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      the reg. */
846ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (guardT == IRTemp_INVALID) {
847ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* unconditional write */
848ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      llPutFReg( fregNo, e );
849ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
850ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      llPutFReg( fregNo,
851ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 IRExpr_Mux0X( unop(Iop_32to8, mkexpr(guardT)),
852ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               llGetFReg(fregNo),
853ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               e ));
854ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
855ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
856ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
857ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
858ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* ---------------- Misc registers ---------------- */
859ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
860ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void putMiscReg32 ( UInt    gsoffset,
861ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           IRExpr* e, /* :: Ity_I32 */
862ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           IRTemp  guardT /* :: Ity_I32, 0 or 1 */)
863ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
864ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (gsoffset) {
865ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case OFFB_FPSCR:   break;
866ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case OFFB_QFLAG32: break;
867ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case OFFB_GEFLAG0: break;
868ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case OFFB_GEFLAG1: break;
869ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case OFFB_GEFLAG2: break;
870ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case OFFB_GEFLAG3: break;
871ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default: vassert(0); /* awaiting more cases */
872ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
873ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I32);
874ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
875ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (guardT == IRTemp_INVALID) {
876ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* unconditional write */
877ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      stmt(IRStmt_Put(gsoffset, e));
878ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
879ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      stmt(IRStmt_Put(
880ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         gsoffset,
881ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRExpr_Mux0X( unop(Iop_32to8, mkexpr(guardT)),
882ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       IRExpr_Get(gsoffset, Ity_I32),
883ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       e
884ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         )
885ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ));
886ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
887ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
888ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
889ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRTemp get_ITSTATE ( void )
890ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
891ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ASSERT_IS_THUMB;
892ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp t = newTemp(Ity_I32);
893ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign(t, IRExpr_Get( OFFB_ITSTATE, Ity_I32));
894ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return t;
895ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
896ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
897ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void put_ITSTATE ( IRTemp t )
898ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
899ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ASSERT_IS_THUMB;
900ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   stmt( IRStmt_Put( OFFB_ITSTATE, mkexpr(t)) );
901ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
902ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
903ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRTemp get_QFLAG32 ( void )
904ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
905ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp t = newTemp(Ity_I32);
906ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign(t, IRExpr_Get( OFFB_QFLAG32, Ity_I32));
907ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return t;
908ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
909ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
910ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void put_QFLAG32 ( IRTemp t, IRTemp condT )
911ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
912ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   putMiscReg32( OFFB_QFLAG32, mkexpr(t), condT );
913ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
914ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
915ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Stickily set the 'Q' flag (APSR bit 27) of the APSR (Application Program
916ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Status Register) to indicate that overflow or saturation occurred.
917ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Nb: t must be zero to denote no saturation, and any nonzero
918ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   value to indicate saturation. */
919ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void or_into_QFLAG32 ( IRExpr* e, IRTemp condT )
920ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
921ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp old = get_QFLAG32();
922ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp nyu = newTemp(Ity_I32);
923ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign(nyu, binop(Iop_Or32, mkexpr(old), e) );
924ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   put_QFLAG32(nyu, condT);
925ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
926ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
927ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Generate code to set APSR.GE[flagNo]. Each fn call sets 1 bit.
928ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   flagNo: which flag bit to set [3...0]
929ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   lowbits_to_ignore:  0 = look at all 32 bits
930ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       8 = look at top 24 bits only
931ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      16 = look at top 16 bits only
932ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      31 = look at the top bit only
933ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   e: input value to be evaluated.
934ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   The new value is taken from 'e' with the lowest 'lowbits_to_ignore'
935ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   masked out.  If the resulting value is zero then the GE flag is
936ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   set to 0; any other value sets the flag to 1. */
937ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void put_GEFLAG32 ( Int flagNo,            /* 0, 1, 2 or 3 */
938ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           Int lowbits_to_ignore, /* 0, 8, 16 or 31   */
939ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           IRExpr* e,             /* Ity_I32 */
940ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           IRTemp condT )
941ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
942ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert( flagNo >= 0 && flagNo <= 3 );
943ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert( lowbits_to_ignore == 0  ||
944ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            lowbits_to_ignore == 8  ||
945ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            lowbits_to_ignore == 16 ||
946ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            lowbits_to_ignore == 31 );
947ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp masked = newTemp(Ity_I32);
948ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign(masked, binop(Iop_Shr32, e, mkU8(lowbits_to_ignore)));
949ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
950ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (flagNo) {
951ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0: putMiscReg32(OFFB_GEFLAG0, mkexpr(masked), condT); break;
952ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 1: putMiscReg32(OFFB_GEFLAG1, mkexpr(masked), condT); break;
953ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 2: putMiscReg32(OFFB_GEFLAG2, mkexpr(masked), condT); break;
954ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 3: putMiscReg32(OFFB_GEFLAG3, mkexpr(masked), condT); break;
955ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default: vassert(0);
956ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
957ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
958ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
959ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Return the (32-bit, zero-or-nonzero representation scheme) of
960ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   the specified GE flag. */
961ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRExpr* get_GEFLAG32( Int flagNo /* 0, 1, 2, 3 */ )
962ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
963ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (flagNo) {
964ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0: return IRExpr_Get( OFFB_GEFLAG0, Ity_I32 );
965ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 1: return IRExpr_Get( OFFB_GEFLAG1, Ity_I32 );
966ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 2: return IRExpr_Get( OFFB_GEFLAG2, Ity_I32 );
967ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 3: return IRExpr_Get( OFFB_GEFLAG3, Ity_I32 );
968ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default: vassert(0);
969ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
970ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
971ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
972ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Set all 4 GE flags from the given 32-bit value as follows: GE 3 and
973ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   2 are set from bit 31 of the value, and GE 1 and 0 are set from bit
974ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   15 of the value.  All other bits are ignored. */
975ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void set_GE_32_10_from_bits_31_15 ( IRTemp t32, IRTemp condT )
976ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
977ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp ge10 = newTemp(Ity_I32);
978ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp ge32 = newTemp(Ity_I32);
979ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign(ge10, binop(Iop_And32, mkexpr(t32), mkU32(0x00008000)));
980ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign(ge32, binop(Iop_And32, mkexpr(t32), mkU32(0x80000000)));
981ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   put_GEFLAG32( 0, 0, mkexpr(ge10), condT );
982ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   put_GEFLAG32( 1, 0, mkexpr(ge10), condT );
983ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   put_GEFLAG32( 2, 0, mkexpr(ge32), condT );
984ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   put_GEFLAG32( 3, 0, mkexpr(ge32), condT );
985ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
986ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
987ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
988ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Set all 4 GE flags from the given 32-bit value as follows: GE 3
989ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   from bit 31, GE 2 from bit 23, GE 1 from bit 15, and GE0 from
990ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   bit 7.  All other bits are ignored. */
991ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void set_GE_3_2_1_0_from_bits_31_23_15_7 ( IRTemp t32, IRTemp condT )
992ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
993ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp ge0 = newTemp(Ity_I32);
994ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp ge1 = newTemp(Ity_I32);
995ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp ge2 = newTemp(Ity_I32);
996ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp ge3 = newTemp(Ity_I32);
997ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign(ge0, binop(Iop_And32, mkexpr(t32), mkU32(0x00000080)));
998ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign(ge1, binop(Iop_And32, mkexpr(t32), mkU32(0x00008000)));
999ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign(ge2, binop(Iop_And32, mkexpr(t32), mkU32(0x00800000)));
1000ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign(ge3, binop(Iop_And32, mkexpr(t32), mkU32(0x80000000)));
1001ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   put_GEFLAG32( 0, 0, mkexpr(ge0), condT );
1002ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   put_GEFLAG32( 1, 0, mkexpr(ge1), condT );
1003ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   put_GEFLAG32( 2, 0, mkexpr(ge2), condT );
1004ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   put_GEFLAG32( 3, 0, mkexpr(ge3), condT );
1005ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1006ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1007ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1008ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* ---------------- FPSCR stuff ---------------- */
1009ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1010ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Generate IR to get hold of the rounding mode bits in FPSCR, and
1011ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   convert them to IR format.  Bind the final result to the
1012ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   returned temp. */
1013ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRTemp /* :: Ity_I32 */ mk_get_IR_rounding_mode ( void )
1014ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1015ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* The ARMvfp encoding for rounding mode bits is:
1016ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         00  to nearest
1017ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         01  to +infinity
1018ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         10  to -infinity
1019ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         11  to zero
1020ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      We need to convert that to the IR encoding:
1021ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         00  to nearest (the default)
1022ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         10  to +infinity
1023ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         01  to -infinity
1024ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         11  to zero
1025ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Which can be done by swapping bits 0 and 1.
1026ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      The rmode bits are at 23:22 in FPSCR.
1027ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   */
1028ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp armEncd = newTemp(Ity_I32);
1029ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp swapped = newTemp(Ity_I32);
1030ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Fish FPSCR[23:22] out, and slide to bottom.  Doesn't matter that
1031ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      we don't zero out bits 24 and above, since the assignment to
1032ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      'swapped' will mask them out anyway. */
1033ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign(armEncd,
1034ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          binop(Iop_Shr32, IRExpr_Get(OFFB_FPSCR, Ity_I32), mkU8(22)));
1035ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Now swap them. */
1036ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign(swapped,
1037ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          binop(Iop_Or32,
1038ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                binop(Iop_And32,
1039ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      binop(Iop_Shl32, mkexpr(armEncd), mkU8(1)),
1040ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      mkU32(2)),
1041ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                binop(Iop_And32,
1042ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      binop(Iop_Shr32, mkexpr(armEncd), mkU8(1)),
1043ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      mkU32(1))
1044ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ));
1045ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return swapped;
1046ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1047ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1048ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1049ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
1050ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Helpers for flag handling and conditional insns      ---*/
1051ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
1052ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1053ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic HChar* name_ARMCondcode ( ARMCondcode cond )
1054ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1055ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (cond) {
1056ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case ARMCondEQ:  return "{eq}";
1057ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case ARMCondNE:  return "{ne}";
1058ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case ARMCondHS:  return "{hs}";  // or 'cs'
1059ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case ARMCondLO:  return "{lo}";  // or 'cc'
1060ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case ARMCondMI:  return "{mi}";
1061ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case ARMCondPL:  return "{pl}";
1062ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case ARMCondVS:  return "{vs}";
1063ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case ARMCondVC:  return "{vc}";
1064ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case ARMCondHI:  return "{hi}";
1065ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case ARMCondLS:  return "{ls}";
1066ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case ARMCondGE:  return "{ge}";
1067ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case ARMCondLT:  return "{lt}";
1068ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case ARMCondGT:  return "{gt}";
1069ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case ARMCondLE:  return "{le}";
1070ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case ARMCondAL:  return ""; // {al}: is the default
1071ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case ARMCondNV:  return "{nv}";
1072ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default: vpanic("name_ARMCondcode");
1073ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1074ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1075ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* and a handy shorthand for it */
1076ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic HChar* nCC ( ARMCondcode cond ) {
1077ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return name_ARMCondcode(cond);
1078ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1079ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1080ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1081ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Build IR to calculate some particular condition from stored
1082ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   CC_OP/CC_DEP1/CC_DEP2/CC_NDEP.  Returns an expression of type
1083ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Ity_I32, suitable for narrowing.  Although the return type is
1084ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Ity_I32, the returned value is either 0 or 1.  'cond' must be
1085ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   :: Ity_I32 and must denote the condition to compute in
1086ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   bits 7:4, and be zero everywhere else.
1087ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
1088ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRExpr* mk_armg_calculate_condition_dyn ( IRExpr* cond )
1089ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1090ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(typeOfIRExpr(irsb->tyenv, cond) == Ity_I32);
1091b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   /* And 'cond' had better produce a value in which only bits 7:4 are
1092b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      nonzero.  However, obviously we can't assert for that. */
1093ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1094ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* So what we're constructing for the first argument is
1095b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      "(cond << 4) | stored-operation".
1096b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      However, as per comments above, 'cond' must be supplied
1097b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      pre-shifted to this function.
1098ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1099ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      This pairing scheme requires that the ARM_CC_OP_ values all fit
1100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      in 4 bits.  Hence we are passing a (COND, OP) pair in the lowest
1101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      8 bits of the first argument. */
1102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRExpr** args
1103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      = mkIRExprVec_4(
1104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           binop(Iop_Or32, IRExpr_Get(OFFB_CC_OP, Ity_I32), cond),
1105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           IRExpr_Get(OFFB_CC_DEP1, Ity_I32),
1106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           IRExpr_Get(OFFB_CC_DEP2, Ity_I32),
1107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           IRExpr_Get(OFFB_CC_NDEP, Ity_I32)
1108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        );
1109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRExpr* call
1110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      = mkIRExprCCall(
1111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           Ity_I32,
1112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           0/*regparm*/,
1113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           "armg_calculate_condition", &armg_calculate_condition,
1114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           args
1115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        );
1116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Exclude the requested condition, OP and NDEP from definedness
1118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      checking.  We're only interested in DEP1 and DEP2. */
1119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   call->Iex.CCall.cee->mcx_mask = (1<<0) | (1<<3);
1120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return call;
1121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Build IR to calculate some particular condition from stored
1125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   CC_OP/CC_DEP1/CC_DEP2/CC_NDEP.  Returns an expression of type
1126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Ity_I32, suitable for narrowing.  Although the return type is
1127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Ity_I32, the returned value is either 0 or 1.
1128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
1129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRExpr* mk_armg_calculate_condition ( ARMCondcode cond )
1130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  /* First arg is "(cond << 4) | condition".  This requires that the
1132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     ARM_CC_OP_ values all fit in 4 bits.  Hence we are passing a
1133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     (COND, OP) pair in the lowest 8 bits of the first argument. */
1134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(cond >= 0 && cond <= 15);
1135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return mk_armg_calculate_condition_dyn( mkU32(cond << 4) );
1136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Build IR to calculate just the carry flag from stored
1140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   CC_OP/CC_DEP1/CC_DEP2/CC_NDEP.  Returns an expression ::
1141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Ity_I32. */
1142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRExpr* mk_armg_calculate_flag_c ( void )
1143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRExpr** args
1145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      = mkIRExprVec_4( IRExpr_Get(OFFB_CC_OP,   Ity_I32),
1146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       IRExpr_Get(OFFB_CC_DEP1, Ity_I32),
1147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       IRExpr_Get(OFFB_CC_DEP2, Ity_I32),
1148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       IRExpr_Get(OFFB_CC_NDEP, Ity_I32) );
1149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRExpr* call
1150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      = mkIRExprCCall(
1151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           Ity_I32,
1152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           0/*regparm*/,
1153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           "armg_calculate_flag_c", &armg_calculate_flag_c,
1154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           args
1155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        );
1156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Exclude OP and NDEP from definedness checking.  We're only
1157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      interested in DEP1 and DEP2. */
1158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   call->Iex.CCall.cee->mcx_mask = (1<<0) | (1<<3);
1159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return call;
1160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Build IR to calculate just the overflow flag from stored
1164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   CC_OP/CC_DEP1/CC_DEP2/CC_NDEP.  Returns an expression ::
1165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Ity_I32. */
1166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRExpr* mk_armg_calculate_flag_v ( void )
1167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRExpr** args
1169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      = mkIRExprVec_4( IRExpr_Get(OFFB_CC_OP,   Ity_I32),
1170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       IRExpr_Get(OFFB_CC_DEP1, Ity_I32),
1171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       IRExpr_Get(OFFB_CC_DEP2, Ity_I32),
1172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       IRExpr_Get(OFFB_CC_NDEP, Ity_I32) );
1173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRExpr* call
1174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      = mkIRExprCCall(
1175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           Ity_I32,
1176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           0/*regparm*/,
1177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           "armg_calculate_flag_v", &armg_calculate_flag_v,
1178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           args
1179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        );
1180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Exclude OP and NDEP from definedness checking.  We're only
1181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      interested in DEP1 and DEP2. */
1182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   call->Iex.CCall.cee->mcx_mask = (1<<0) | (1<<3);
1183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return call;
1184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Build IR to calculate N Z C V in bits 31:28 of the
1188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   returned word. */
1189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRExpr* mk_armg_calculate_flags_nzcv ( void )
1190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRExpr** args
1192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      = mkIRExprVec_4( IRExpr_Get(OFFB_CC_OP,   Ity_I32),
1193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       IRExpr_Get(OFFB_CC_DEP1, Ity_I32),
1194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       IRExpr_Get(OFFB_CC_DEP2, Ity_I32),
1195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       IRExpr_Get(OFFB_CC_NDEP, Ity_I32) );
1196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRExpr* call
1197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      = mkIRExprCCall(
1198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           Ity_I32,
1199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           0/*regparm*/,
1200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           "armg_calculate_flags_nzcv", &armg_calculate_flags_nzcv,
1201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           args
1202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        );
1203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Exclude OP and NDEP from definedness checking.  We're only
1204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      interested in DEP1 and DEP2. */
1205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   call->Iex.CCall.cee->mcx_mask = (1<<0) | (1<<3);
1206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return call;
1207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRExpr* mk_armg_calculate_flag_qc ( IRExpr* resL, IRExpr* resR, Bool Q )
1210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRExpr** args1;
1212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRExpr** args2;
1213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRExpr *call1, *call2, *res;
1214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (Q) {
1216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      args1 = mkIRExprVec_4 ( binop(Iop_GetElem32x4, resL, mkU8(0)),
1217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              binop(Iop_GetElem32x4, resL, mkU8(1)),
1218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              binop(Iop_GetElem32x4, resR, mkU8(0)),
1219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              binop(Iop_GetElem32x4, resR, mkU8(1)) );
1220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      args2 = mkIRExprVec_4 ( binop(Iop_GetElem32x4, resL, mkU8(2)),
1221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              binop(Iop_GetElem32x4, resL, mkU8(3)),
1222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              binop(Iop_GetElem32x4, resR, mkU8(2)),
1223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              binop(Iop_GetElem32x4, resR, mkU8(3)) );
1224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
1225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      args1 = mkIRExprVec_4 ( binop(Iop_GetElem32x2, resL, mkU8(0)),
1226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              binop(Iop_GetElem32x2, resL, mkU8(1)),
1227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              binop(Iop_GetElem32x2, resR, mkU8(0)),
1228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              binop(Iop_GetElem32x2, resR, mkU8(1)) );
1229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if 1
1232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   call1 = mkIRExprCCall(
1233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             Ity_I32,
1234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             0/*regparm*/,
1235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             "armg_calculate_flag_qc", &armg_calculate_flag_qc,
1236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             args1
1237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          );
1238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (Q) {
1239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      call2 = mkIRExprCCall(
1240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                Ity_I32,
1241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                0/*regparm*/,
1242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                "armg_calculate_flag_qc", &armg_calculate_flag_qc,
1243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                args2
1244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             );
1245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (Q) {
1247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      res = binop(Iop_Or32, call1, call2);
1248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
1249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      res = call1;
1250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#else
1252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (Q) {
1253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      res = unop(Iop_1Uto32,
1254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 binop(Iop_CmpNE32,
1255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       binop(Iop_Or32,
1256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             binop(Iop_Or32,
1257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                   binop(Iop_Xor32,
1258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                         args1[0],
1259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                         args1[2]),
1260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                   binop(Iop_Xor32,
1261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                         args1[1],
1262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                         args1[3])),
1263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             binop(Iop_Or32,
1264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                   binop(Iop_Xor32,
1265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                         args2[0],
1266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                         args2[2]),
1267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                   binop(Iop_Xor32,
1268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                         args2[1],
1269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                         args2[3]))),
1270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       mkU32(0)));
1271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
1272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      res = unop(Iop_1Uto32,
1273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 binop(Iop_CmpNE32,
1274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       binop(Iop_Or32,
1275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             binop(Iop_Xor32,
1276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                   args1[0],
1277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                   args1[2]),
1278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             binop(Iop_Xor32,
1279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                   args1[1],
1280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                   args1[3])),
1281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       mkU32(0)));
1282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
1284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return res;
1285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// FIXME: this is named wrongly .. looks like a sticky set of
1288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// QC, not a write to it.
1289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void setFlag_QC ( IRExpr* resL, IRExpr* resR, Bool Q,
1290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         IRTemp condT )
1291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   putMiscReg32 (OFFB_FPSCR,
1293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 binop(Iop_Or32,
1294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       IRExpr_Get(OFFB_FPSCR, Ity_I32),
1295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       binop(Iop_Shl32,
1296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             mk_armg_calculate_flag_qc(resL, resR, Q),
1297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             mkU8(27))),
1298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 condT);
1299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Build IR to conditionally set the flags thunk.  As with putIReg, if
1302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   guard is IRTemp_INVALID then it's unconditional, else it holds a
1303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   condition :: Ity_I32. */
1304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
1305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid setFlags_D1_D2_ND ( UInt cc_op, IRTemp t_dep1,
1306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         IRTemp t_dep2, IRTemp t_ndep,
1307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         IRTemp guardT /* :: Ity_I32, 0 or 1 */ )
1308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp c8;
1310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(typeOfIRTemp(irsb->tyenv, t_dep1 == Ity_I32));
1311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(typeOfIRTemp(irsb->tyenv, t_dep2 == Ity_I32));
1312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(typeOfIRTemp(irsb->tyenv, t_ndep == Ity_I32));
1313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(cc_op >= ARMG_CC_OP_COPY && cc_op < ARMG_CC_OP_NUMBER);
1314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (guardT == IRTemp_INVALID) {
1315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* unconditional */
1316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      stmt( IRStmt_Put( OFFB_CC_OP,   mkU32(cc_op) ));
1317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      stmt( IRStmt_Put( OFFB_CC_DEP1, mkexpr(t_dep1) ));
1318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      stmt( IRStmt_Put( OFFB_CC_DEP2, mkexpr(t_dep2) ));
1319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      stmt( IRStmt_Put( OFFB_CC_NDEP, mkexpr(t_ndep) ));
1320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
1321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* conditional */
1322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      c8 = newTemp(Ity_I8);
1323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( c8, unop(Iop_32to8, mkexpr(guardT)) );
1324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      stmt( IRStmt_Put(
1325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               OFFB_CC_OP,
1326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               IRExpr_Mux0X( mkexpr(c8),
1327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             IRExpr_Get(OFFB_CC_OP, Ity_I32),
1328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             mkU32(cc_op) )));
1329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      stmt( IRStmt_Put(
1330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               OFFB_CC_DEP1,
1331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               IRExpr_Mux0X( mkexpr(c8),
1332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             IRExpr_Get(OFFB_CC_DEP1, Ity_I32),
1333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             mkexpr(t_dep1) )));
1334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      stmt( IRStmt_Put(
1335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               OFFB_CC_DEP2,
1336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               IRExpr_Mux0X( mkexpr(c8),
1337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             IRExpr_Get(OFFB_CC_DEP2, Ity_I32),
1338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             mkexpr(t_dep2) )));
1339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      stmt( IRStmt_Put(
1340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               OFFB_CC_NDEP,
1341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               IRExpr_Mux0X( mkexpr(c8),
1342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             IRExpr_Get(OFFB_CC_NDEP, Ity_I32),
1343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             mkexpr(t_ndep) )));
1344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Minor variant of the above that sets NDEP to zero (if it
1349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   sets it at all) */
1350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void setFlags_D1_D2 ( UInt cc_op, IRTemp t_dep1,
1351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             IRTemp t_dep2,
1352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             IRTemp guardT /* :: Ity_I32, 0 or 1 */ )
1353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp z32 = newTemp(Ity_I32);
1355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign( z32, mkU32(0) );
1356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   setFlags_D1_D2_ND( cc_op, t_dep1, t_dep2, z32, guardT );
1357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Minor variant of the above that sets DEP2 to zero (if it
1361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   sets it at all) */
1362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void setFlags_D1_ND ( UInt cc_op, IRTemp t_dep1,
1363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             IRTemp t_ndep,
1364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             IRTemp guardT /* :: Ity_I32, 0 or 1 */ )
1365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp z32 = newTemp(Ity_I32);
1367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign( z32, mkU32(0) );
1368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   setFlags_D1_D2_ND( cc_op, t_dep1, z32, t_ndep, guardT );
1369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Minor variant of the above that sets DEP2 and NDEP to zero (if it
1373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   sets them at all) */
1374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void setFlags_D1 ( UInt cc_op, IRTemp t_dep1,
1375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          IRTemp guardT /* :: Ity_I32, 0 or 1 */ )
1376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp z32 = newTemp(Ity_I32);
1378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign( z32, mkU32(0) );
1379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   setFlags_D1_D2_ND( cc_op, t_dep1, z32, z32, guardT );
1380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* ARM only */
1384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Generate a side-exit to the next instruction, if the given guard
1385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   expression :: Ity_I32 is 0 (note!  the side exit is taken if the
1386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   condition is false!)  This is used to skip over conditional
1387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   instructions which we can't generate straight-line code for, either
1388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   because they are too complex or (more likely) they potentially
1389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   generate exceptions.
1390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
1391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void mk_skip_over_A32_if_cond_is_false (
1392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               IRTemp guardT /* :: Ity_I32, 0 or 1 */
1393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            )
1394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ASSERT_IS_ARM;
1396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(guardT != IRTemp_INVALID);
1397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(0 == (guest_R15_curr_instr_notENC & 3));
1398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   stmt( IRStmt_Exit(
1399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            unop(Iop_Not1, unop(Iop_32to1, mkexpr(guardT))),
1400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            Ijk_Boring,
1401663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            IRConst_U32(toUInt(guest_R15_curr_instr_notENC + 4)),
1402663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            OFFB_R15T
1403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       ));
1404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Thumb16 only */
1407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* ditto, but jump over a 16-bit thumb insn */
1408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void mk_skip_over_T16_if_cond_is_false (
1409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               IRTemp guardT /* :: Ity_I32, 0 or 1 */
1410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            )
1411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ASSERT_IS_THUMB;
1413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(guardT != IRTemp_INVALID);
1414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(0 == (guest_R15_curr_instr_notENC & 1));
1415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   stmt( IRStmt_Exit(
1416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            unop(Iop_Not1, unop(Iop_32to1, mkexpr(guardT))),
1417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            Ijk_Boring,
1418663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            IRConst_U32(toUInt((guest_R15_curr_instr_notENC + 2) | 1)),
1419663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            OFFB_R15T
1420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       ));
1421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Thumb32 only */
1425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* ditto, but jump over a 32-bit thumb insn */
1426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void mk_skip_over_T32_if_cond_is_false (
1427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               IRTemp guardT /* :: Ity_I32, 0 or 1 */
1428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            )
1429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ASSERT_IS_THUMB;
1431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(guardT != IRTemp_INVALID);
1432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(0 == (guest_R15_curr_instr_notENC & 1));
1433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   stmt( IRStmt_Exit(
1434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            unop(Iop_Not1, unop(Iop_32to1, mkexpr(guardT))),
1435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            Ijk_Boring,
1436663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            IRConst_U32(toUInt((guest_R15_curr_instr_notENC + 4) | 1)),
1437663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            OFFB_R15T
1438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       ));
1439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Thumb16 and Thumb32 only
1443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Generate a SIGILL followed by a restart of the current instruction
1444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if the given temp is nonzero. */
1445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void gen_SIGILL_T_if_nonzero ( IRTemp t /* :: Ity_I32 */ )
1446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ASSERT_IS_THUMB;
1448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(t != IRTemp_INVALID);
1449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(0 == (guest_R15_curr_instr_notENC & 1));
1450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   stmt(
1451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRStmt_Exit(
1452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         binop(Iop_CmpNE32, mkexpr(t), mkU32(0)),
1453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         Ijk_NoDecode,
1454663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRConst_U32(toUInt(guest_R15_curr_instr_notENC | 1)),
1455663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         OFFB_R15T
1456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      )
1457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   );
1458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Inspect the old_itstate, and generate a SIGILL if it indicates that
1462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   we are currently in an IT block and are not the last in the block.
1463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   This also rolls back guest_ITSTATE to its old value before the exit
1464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   and restores it to its new value afterwards.  This is so that if
1465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   the exit is taken, we have an up to date version of ITSTATE
1466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   available.  Without doing that, we have no hope of making precise
1467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   exceptions work. */
1468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void gen_SIGILL_T_if_in_but_NLI_ITBlock (
1469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               IRTemp old_itstate /* :: Ity_I32 */,
1470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               IRTemp new_itstate /* :: Ity_I32 */
1471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            )
1472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ASSERT_IS_THUMB;
1474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   put_ITSTATE(old_itstate); // backout
1475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp guards_for_next3 = newTemp(Ity_I32);
1476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign(guards_for_next3,
1477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          binop(Iop_Shr32, mkexpr(old_itstate), mkU8(8)));
1478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   gen_SIGILL_T_if_nonzero(guards_for_next3);
1479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   put_ITSTATE(new_itstate); //restore
1480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Simpler version of the above, which generates a SIGILL if
1484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   we're anywhere within an IT block. */
1485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void gen_SIGILL_T_if_in_ITBlock (
1486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               IRTemp old_itstate /* :: Ity_I32 */,
1487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               IRTemp new_itstate /* :: Ity_I32 */
1488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            )
1489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   put_ITSTATE(old_itstate); // backout
1491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   gen_SIGILL_T_if_nonzero(old_itstate);
1492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   put_ITSTATE(new_itstate); //restore
1493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Generate an APSR value, from the NZCV thunk, and
1497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   from QFLAG32 and GEFLAG0 .. GEFLAG3. */
1498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRTemp synthesise_APSR ( void )
1499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp res1 = newTemp(Ity_I32);
1501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // Get NZCV
1502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign( res1, mk_armg_calculate_flags_nzcv() );
1503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // OR in the Q value
1504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp res2 = newTemp(Ity_I32);
1505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign(
1506ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      res2,
1507ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      binop(Iop_Or32,
1508ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            mkexpr(res1),
1509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            binop(Iop_Shl32,
1510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  unop(Iop_1Uto32,
1511ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       binop(Iop_CmpNE32,
1512ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             mkexpr(get_QFLAG32()),
1513ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             mkU32(0))),
1514ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  mkU8(ARMG_CC_SHIFT_Q)))
1515ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   );
1516ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // OR in GE0 .. GE3
1517ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRExpr* ge0
1518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      = unop(Iop_1Uto32, binop(Iop_CmpNE32, get_GEFLAG32(0), mkU32(0)));
1519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRExpr* ge1
1520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      = unop(Iop_1Uto32, binop(Iop_CmpNE32, get_GEFLAG32(1), mkU32(0)));
1521ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRExpr* ge2
1522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      = unop(Iop_1Uto32, binop(Iop_CmpNE32, get_GEFLAG32(2), mkU32(0)));
1523ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRExpr* ge3
1524ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      = unop(Iop_1Uto32, binop(Iop_CmpNE32, get_GEFLAG32(3), mkU32(0)));
1525ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp res3 = newTemp(Ity_I32);
1526ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign(res3,
1527ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          binop(Iop_Or32,
1528ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                mkexpr(res2),
1529ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                binop(Iop_Or32,
1530ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      binop(Iop_Or32,
1531ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            binop(Iop_Shl32, ge0, mkU8(16)),
1532ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            binop(Iop_Shl32, ge1, mkU8(17))),
1533ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      binop(Iop_Or32,
1534ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            binop(Iop_Shl32, ge2, mkU8(18)),
1535ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            binop(Iop_Shl32, ge3, mkU8(19))) )));
1536ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return res3;
1537ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1538ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1539ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1540ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* and the inverse transformation: given an APSR value,
1541ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   set the NZCV thunk, the Q flag, and the GE flags. */
1542ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void desynthesise_APSR ( Bool write_nzcvq, Bool write_ge,
1543ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                IRTemp apsrT, IRTemp condT )
1544ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1545ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(write_nzcvq || write_ge);
1546ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (write_nzcvq) {
1547ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // Do NZCV
1548ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp immT = newTemp(Ity_I32);
1549ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign(immT, binop(Iop_And32, mkexpr(apsrT), mkU32(0xF0000000)) );
1550ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      setFlags_D1(ARMG_CC_OP_COPY, immT, condT);
1551ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // Do Q
1552ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp qnewT = newTemp(Ity_I32);
1553ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign(qnewT, binop(Iop_And32, mkexpr(apsrT), mkU32(ARMG_CC_MASK_Q)));
1554ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      put_QFLAG32(qnewT, condT);
1555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (write_ge) {
1557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // Do GE3..0
1558ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      put_GEFLAG32(0, 0, binop(Iop_And32, mkexpr(apsrT), mkU32(1<<16)),
1559ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   condT);
1560ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      put_GEFLAG32(1, 0, binop(Iop_And32, mkexpr(apsrT), mkU32(1<<17)),
1561ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   condT);
1562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      put_GEFLAG32(2, 0, binop(Iop_And32, mkexpr(apsrT), mkU32(1<<18)),
1563ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   condT);
1564ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      put_GEFLAG32(3, 0, binop(Iop_And32, mkexpr(apsrT), mkU32(1<<19)),
1565ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   condT);
1566ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1567ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1568ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1570ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
1571ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Helpers for saturation                               ---*/
1572ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
1573ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1574ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* FIXME: absolutely the only diff. between (a) armUnsignedSatQ and
1575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   (b) armSignedSatQ is that in (a) the floor is set to 0, whereas in
1576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   (b) the floor is computed from the value of imm5.  these two fnsn
1577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   should be commoned up. */
1578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* UnsignedSatQ(): 'clamp' each value so it lies between 0 <= x <= (2^N)-1
1580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Optionally return flag resQ saying whether saturation occurred.
1581ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   See definition in manual, section A2.2.1, page 41
1582ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   (bits(N), boolean) UnsignedSatQ( integer i, integer N )
1583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   {
1584ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     if ( i > (2^N)-1 ) { result = (2^N)-1; saturated = TRUE; }
1585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     elsif ( i < 0 )    { result = 0; saturated = TRUE; }
1586ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     else               { result = i; saturated = FALSE; }
1587ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     return ( result<N-1:0>, saturated );
1588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
1590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void armUnsignedSatQ( IRTemp* res,  /* OUT - Ity_I32 */
1591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             IRTemp* resQ, /* OUT - Ity_I32  */
1592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             IRTemp regT,  /* value to clamp - Ity_I32 */
1593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             UInt imm5 )   /* saturation ceiling */
1594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt ceil  = (1 << imm5) - 1;    // (2^imm5)-1
1596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt floor = 0;
1597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp node0 = newTemp(Ity_I32);
1599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp node1 = newTemp(Ity_I32);
1600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp node2 = newTemp(Ity_I1);
1601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp node3 = newTemp(Ity_I32);
1602ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp node4 = newTemp(Ity_I32);
1603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp node5 = newTemp(Ity_I1);
1604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp node6 = newTemp(Ity_I32);
1605ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign( node0, mkexpr(regT) );
1607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign( node1, mkU32(ceil) );
1608ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign( node2, binop( Iop_CmpLT32S, mkexpr(node1), mkexpr(node0) ) );
1609ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign( node3, IRExpr_Mux0X( unop(Iop_1Uto8, mkexpr(node2)),
1610ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                mkexpr(node0),
1611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                mkexpr(node1) ) );
1612ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign( node4, mkU32(floor) );
1613ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign( node5, binop( Iop_CmpLT32S, mkexpr(node3), mkexpr(node4) ) );
1614ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign( node6, IRExpr_Mux0X( unop(Iop_1Uto8, mkexpr(node5)),
1615ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                mkexpr(node3),
1616ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                mkexpr(node4) ) );
1617ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign( *res, mkexpr(node6) );
1618ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1619ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* if saturation occurred, then resQ is set to some nonzero value
1620ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if sat did not occur, resQ is guaranteed to be zero. */
1621ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (resQ) {
1622ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( *resQ, binop(Iop_Xor32, mkexpr(*res), mkexpr(regT)) );
1623ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1624ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1625ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1626ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1627ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* SignedSatQ(): 'clamp' each value so it lies between  -2^N <= x <= (2^N) - 1
1628ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Optionally return flag resQ saying whether saturation occurred.
1629ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   - see definition in manual, section A2.2.1, page 41
1630ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   (bits(N), boolean ) SignedSatQ( integer i, integer N )
1631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   {
1632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     if ( i > 2^(N-1) - 1 )    { result = 2^(N-1) - 1; saturated = TRUE; }
1633ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     elsif ( i < -(2^(N-1)) )  { result = -(2^(N-1));  saturated = FALSE; }
1634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     else                      { result = i;           saturated = FALSE; }
1635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     return ( result[N-1:0], saturated );
1636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
1638ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void armSignedSatQ( IRTemp regT,    /* value to clamp - Ity_I32 */
1639ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           UInt imm5,      /* saturation ceiling */
1640ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           IRTemp* res,    /* OUT - Ity_I32 */
1641ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           IRTemp* resQ )  /* OUT - Ity_I32  */
1642ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1643ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int ceil  =  (1 << (imm5-1)) - 1;  //  (2^(imm5-1))-1
1644ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int floor = -(1 << (imm5-1));      // -(2^(imm5-1))
1645ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1646ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp node0 = newTemp(Ity_I32);
1647ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp node1 = newTemp(Ity_I32);
1648ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp node2 = newTemp(Ity_I1);
1649ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp node3 = newTemp(Ity_I32);
1650ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp node4 = newTemp(Ity_I32);
1651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp node5 = newTemp(Ity_I1);
1652ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp node6 = newTemp(Ity_I32);
1653ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1654ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign( node0, mkexpr(regT) );
1655ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign( node1, mkU32(ceil) );
1656ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign( node2, binop( Iop_CmpLT32S, mkexpr(node1), mkexpr(node0) ) );
1657ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign( node3, IRExpr_Mux0X( unop(Iop_1Uto8, mkexpr(node2)),
1658ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                mkexpr(node0),  mkexpr(node1) ) );
1659ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign( node4, mkU32(floor) );
1660ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign( node5, binop( Iop_CmpLT32S, mkexpr(node3), mkexpr(node4) ) );
1661ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign( node6, IRExpr_Mux0X( unop(Iop_1Uto8, mkexpr(node5)),
1662ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                mkexpr(node3),  mkexpr(node4) ) );
1663ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign( *res, mkexpr(node6) );
1664ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1665ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* if saturation occurred, then resQ is set to some nonzero value
1666ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if sat did not occur, resQ is guaranteed to be zero. */
1667ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (resQ) {
1668ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     assign( *resQ, binop(Iop_Xor32, mkexpr(*res), mkexpr(regT)) );
1669ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1670ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1671ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1672ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1673ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Compute a value 0 :: I32 or 1 :: I32, indicating whether signed
1674ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   overflow occurred for 32-bit addition.  Needs both args and the
1675ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   result.  HD p27. */
1676ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
1677ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownIRExpr* signed_overflow_after_Add32 ( IRExpr* resE,
1678ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                      IRTemp argL, IRTemp argR )
1679ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1680ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp res = newTemp(Ity_I32);
1681ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign(res, resE);
1682ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return
1683ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      binop( Iop_Shr32,
1684ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             binop( Iop_And32,
1685ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    binop( Iop_Xor32, mkexpr(res), mkexpr(argL) ),
1686ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    binop( Iop_Xor32, mkexpr(res), mkexpr(argR) )),
1687ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             mkU8(31) );
1688ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1689ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1690663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* Similarly .. also from HD p27 .. */
1691663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic
1692663860b1408516d02ebfcb3a9999a134e6cfb223Ben ChengIRExpr* signed_overflow_after_Sub32 ( IRExpr* resE,
1693663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                      IRTemp argL, IRTemp argR )
1694663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
1695663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp res = newTemp(Ity_I32);
1696663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign(res, resE);
1697663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return
1698663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      binop( Iop_Shr32,
1699663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng             binop( Iop_And32,
1700663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    binop( Iop_Xor32, mkexpr(argL), mkexpr(argR) ),
1701663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                    binop( Iop_Xor32, mkexpr(res),  mkexpr(argL) )),
1702663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng             mkU8(31) );
1703663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
1704663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
1705ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1706ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
1707ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Larger helpers                                       ---*/
1708ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
1709ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1710ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Compute both the result and new C flag value for a LSL by an imm5
1711ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   or by a register operand.  May generate reads of the old C value
1712ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   (hence only safe to use before any writes to guest state happen).
1713ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Are factored out so can be used by both ARM and Thumb.
1714ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1715ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Note that in compute_result_and_C_after_{LSL,LSR,ASR}_by{imm5,reg},
1716ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   "res" (the result)  is a.k.a. "shop", shifter operand
1717ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   "newC" (the new C)  is a.k.a. "shco", shifter carry out
1718ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1719ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   The calling convention for res and newC is a bit funny.  They could
1720ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   be passed by value, but instead are passed by ref.
1721b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1722b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   The C (shco) value computed must be zero in bits 31:1, as the IR
1723b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   optimisations for flag handling (guest_arm_spechelper) rely on
1724b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   that, and the slow-path handlers (armg_calculate_flags_nzcv) assert
1725b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   for it.  Same applies to all these functions that compute shco
1726b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   after a shift or rotate, not just this one.
1727ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
1728ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1729ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void compute_result_and_C_after_LSL_by_imm5 (
1730ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               /*OUT*/HChar* buf,
1731ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               IRTemp* res,
1732ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               IRTemp* newC,
1733ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               IRTemp rMt, UInt shift_amt, /* operands */
1734ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               UInt rM      /* only for debug printing */
1735ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            )
1736ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1737ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (shift_amt == 0) {
1738ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (newC) {
1739ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( *newC, mk_armg_calculate_flag_c() );
1740ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1741ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( *res, mkexpr(rMt) );
1742ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIS(buf, "r%u", rM);
1743ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
1744ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert(shift_amt >= 1 && shift_amt <= 31);
1745ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (newC) {
1746ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( *newC,
1747ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 binop(Iop_And32,
1748ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       binop(Iop_Shr32, mkexpr(rMt),
1749ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                        mkU8(32 - shift_amt)),
1750ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       mkU32(1)));
1751ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1752ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( *res,
1753ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              binop(Iop_Shl32, mkexpr(rMt), mkU8(shift_amt)) );
1754ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIS(buf, "r%u, LSL #%u", rM, shift_amt);
1755ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1756ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1757ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1758ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1759ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void compute_result_and_C_after_LSL_by_reg (
1760ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               /*OUT*/HChar* buf,
1761ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               IRTemp* res,
1762ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               IRTemp* newC,
1763ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               IRTemp rMt, IRTemp rSt,  /* operands */
1764ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               UInt rM,    UInt rS      /* only for debug printing */
1765ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            )
1766ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1767ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // shift left in range 0 .. 255
1768ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // amt  = rS & 255
1769ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // res  = amt < 32 ?  Rm << amt  : 0
1770ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // newC = amt == 0     ? oldC  :
1771ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //        amt in 1..32 ?  Rm[32-amt]  : 0
1772ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp amtT = newTemp(Ity_I32);
1773ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign( amtT, binop(Iop_And32, mkexpr(rSt), mkU32(255)) );
1774ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (newC) {
1775ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* mux0X(amt == 0,
1776ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               mux0X(amt < 32,
1777ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     0,
1778b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                     Rm[(32-amt) & 31]),
1779ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               oldC)
1780ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      */
1781ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* About the best you can do is pray that iropt is able
1782ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         to nuke most or all of the following junk. */
1783ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp oldC = newTemp(Ity_I32);
1784ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign(oldC, mk_armg_calculate_flag_c() );
1785ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign(
1786ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *newC,
1787ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRExpr_Mux0X(
1788ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            unop(Iop_1Uto8,
1789ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 binop(Iop_CmpEQ32, mkexpr(amtT), mkU32(0))),
1790ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            IRExpr_Mux0X(
1791ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               unop(Iop_1Uto8,
1792ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    binop(Iop_CmpLE32U, mkexpr(amtT), mkU32(32))),
1793ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               mkU32(0),
1794b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               binop(Iop_And32,
1795b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                     binop(Iop_Shr32,
1796b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                           mkexpr(rMt),
1797b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                           unop(Iop_32to8,
1798b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                binop(Iop_And32,
1799b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                      binop(Iop_Sub32,
1800b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                            mkU32(32),
1801b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                            mkexpr(amtT)),
1802b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                      mkU32(31)
1803b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                )
1804b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                           )
1805b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                     ),
1806b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                     mkU32(1)
1807ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               )
1808ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ),
1809ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            mkexpr(oldC)
1810ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         )
1811ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      );
1812ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1813ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // (Rm << (Rs & 31))  &  (((Rs & 255) - 32) >>s 31)
1814ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // Lhs of the & limits the shift to 31 bits, so as to
1815ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // give known IR semantics.  Rhs of the & is all 1s for
1816ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // Rs <= 31 and all 0s for Rs >= 32.
1817ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign(
1818ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *res,
1819ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      binop(
1820ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         Iop_And32,
1821ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         binop(Iop_Shl32,
1822ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               mkexpr(rMt),
1823ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               unop(Iop_32to8,
1824ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    binop(Iop_And32, mkexpr(rSt), mkU32(31)))),
1825ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         binop(Iop_Sar32,
1826ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               binop(Iop_Sub32,
1827ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     mkexpr(amtT),
1828ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     mkU32(32)),
1829ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               mkU8(31))));
1830ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DIS(buf, "r%u, LSL r%u", rM, rS);
1831ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1832ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1833ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1834ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void compute_result_and_C_after_LSR_by_imm5 (
1835ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               /*OUT*/HChar* buf,
1836ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               IRTemp* res,
1837ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               IRTemp* newC,
1838ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               IRTemp rMt, UInt shift_amt, /* operands */
1839ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               UInt rM      /* only for debug printing */
1840ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            )
1841ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1842ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (shift_amt == 0) {
1843ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // conceptually a 32-bit shift, however:
1844ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // res  = 0
1845ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // newC = Rm[31]
1846ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (newC) {
1847ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( *newC,
1848ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 binop(Iop_And32,
1849ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       binop(Iop_Shr32, mkexpr(rMt), mkU8(31)),
1850ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       mkU32(1)));
1851ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1852ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( *res, mkU32(0) );
1853ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIS(buf, "r%u, LSR #0(a.k.a. 32)", rM);
1854ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
1855ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // shift in range 1..31
1856ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // res  = Rm >>u shift_amt
1857ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // newC = Rm[shift_amt - 1]
1858ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert(shift_amt >= 1 && shift_amt <= 31);
1859ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (newC) {
1860ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( *newC,
1861ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 binop(Iop_And32,
1862ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       binop(Iop_Shr32, mkexpr(rMt),
1863ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                        mkU8(shift_amt - 1)),
1864ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       mkU32(1)));
1865ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1866ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( *res,
1867ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              binop(Iop_Shr32, mkexpr(rMt), mkU8(shift_amt)) );
1868ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIS(buf, "r%u, LSR #%u", rM, shift_amt);
1869ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1870ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1871ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1872ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1873ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void compute_result_and_C_after_LSR_by_reg (
1874ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               /*OUT*/HChar* buf,
1875ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               IRTemp* res,
1876ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               IRTemp* newC,
1877ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               IRTemp rMt, IRTemp rSt,  /* operands */
1878ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               UInt rM,    UInt rS      /* only for debug printing */
1879ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            )
1880ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1881ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // shift right in range 0 .. 255
1882ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // amt = rS & 255
1883ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // res  = amt < 32 ?  Rm >>u amt  : 0
1884ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // newC = amt == 0     ? oldC  :
1885ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //        amt in 1..32 ?  Rm[amt-1]  : 0
1886ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp amtT = newTemp(Ity_I32);
1887ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign( amtT, binop(Iop_And32, mkexpr(rSt), mkU32(255)) );
1888ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (newC) {
1889ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* mux0X(amt == 0,
1890ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               mux0X(amt < 32,
1891ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     0,
1892b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                     Rm[(amt-1) & 31]),
1893ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               oldC)
1894ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      */
1895ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp oldC = newTemp(Ity_I32);
1896ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign(oldC, mk_armg_calculate_flag_c() );
1897ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign(
1898ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *newC,
1899ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRExpr_Mux0X(
1900ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            unop(Iop_1Uto8,
1901ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 binop(Iop_CmpEQ32, mkexpr(amtT), mkU32(0))),
1902ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            IRExpr_Mux0X(
1903ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               unop(Iop_1Uto8,
1904ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    binop(Iop_CmpLE32U, mkexpr(amtT), mkU32(32))),
1905ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               mkU32(0),
1906b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               binop(Iop_And32,
1907b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                     binop(Iop_Shr32,
1908b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                           mkexpr(rMt),
1909b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                           unop(Iop_32to8,
1910b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                binop(Iop_And32,
1911b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                      binop(Iop_Sub32,
1912b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                            mkexpr(amtT),
1913b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                            mkU32(1)),
1914b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                      mkU32(31)
1915b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                )
1916b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                           )
1917b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                     ),
1918b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                     mkU32(1)
1919ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               )
1920ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ),
1921ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            mkexpr(oldC)
1922ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         )
1923ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      );
1924ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1925ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // (Rm >>u (Rs & 31))  &  (((Rs & 255) - 32) >>s 31)
1926ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // Lhs of the & limits the shift to 31 bits, so as to
1927ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // give known IR semantics.  Rhs of the & is all 1s for
1928ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // Rs <= 31 and all 0s for Rs >= 32.
1929ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign(
1930ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *res,
1931ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      binop(
1932ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         Iop_And32,
1933ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         binop(Iop_Shr32,
1934ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               mkexpr(rMt),
1935ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               unop(Iop_32to8,
1936ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    binop(Iop_And32, mkexpr(rSt), mkU32(31)))),
1937ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         binop(Iop_Sar32,
1938ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               binop(Iop_Sub32,
1939ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     mkexpr(amtT),
1940ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     mkU32(32)),
1941ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               mkU8(31))));
1942ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DIS(buf, "r%u, LSR r%u", rM, rS);
1943ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1944ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1945ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1946ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void compute_result_and_C_after_ASR_by_imm5 (
1947ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               /*OUT*/HChar* buf,
1948ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               IRTemp* res,
1949ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               IRTemp* newC,
1950ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               IRTemp rMt, UInt shift_amt, /* operands */
1951ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               UInt rM      /* only for debug printing */
1952ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            )
1953ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1954ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (shift_amt == 0) {
1955ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // conceptually a 32-bit shift, however:
1956ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // res  = Rm >>s 31
1957ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // newC = Rm[31]
1958ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (newC) {
1959ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( *newC,
1960ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 binop(Iop_And32,
1961ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       binop(Iop_Shr32, mkexpr(rMt), mkU8(31)),
1962ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       mkU32(1)));
1963ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1964ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( *res, binop(Iop_Sar32, mkexpr(rMt), mkU8(31)) );
1965ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIS(buf, "r%u, ASR #0(a.k.a. 32)", rM);
1966ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
1967ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // shift in range 1..31
1968ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // res = Rm >>s shift_amt
1969ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // newC = Rm[shift_amt - 1]
1970ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert(shift_amt >= 1 && shift_amt <= 31);
1971ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (newC) {
1972ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( *newC,
1973ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 binop(Iop_And32,
1974ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       binop(Iop_Shr32, mkexpr(rMt),
1975ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                        mkU8(shift_amt - 1)),
1976ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       mkU32(1)));
1977ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1978ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( *res,
1979ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              binop(Iop_Sar32, mkexpr(rMt), mkU8(shift_amt)) );
1980ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIS(buf, "r%u, ASR #%u", rM, shift_amt);
1981ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1982ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1983ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1984ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1985ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void compute_result_and_C_after_ASR_by_reg (
1986ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               /*OUT*/HChar* buf,
1987ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               IRTemp* res,
1988ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               IRTemp* newC,
1989ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               IRTemp rMt, IRTemp rSt,  /* operands */
1990ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               UInt rM,    UInt rS      /* only for debug printing */
1991ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            )
1992ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1993ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // arithmetic shift right in range 0 .. 255
1994ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // amt = rS & 255
1995ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // res  = amt < 32 ?  Rm >>s amt  : Rm >>s 31
1996ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // newC = amt == 0     ? oldC  :
1997ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //        amt in 1..32 ?  Rm[amt-1]  : Rm[31]
1998ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp amtT = newTemp(Ity_I32);
1999ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign( amtT, binop(Iop_And32, mkexpr(rSt), mkU32(255)) );
2000ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (newC) {
2001ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* mux0X(amt == 0,
2002ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               mux0X(amt < 32,
2003ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     Rm[31],
2004ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     Rm[(amt-1) & 31])
2005ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               oldC)
2006ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      */
2007ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp oldC = newTemp(Ity_I32);
2008ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign(oldC, mk_armg_calculate_flag_c() );
2009ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign(
2010ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *newC,
2011ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRExpr_Mux0X(
2012ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            unop(Iop_1Uto8,
2013ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 binop(Iop_CmpEQ32, mkexpr(amtT), mkU32(0))),
2014ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            IRExpr_Mux0X(
2015ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               unop(Iop_1Uto8,
2016ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    binop(Iop_CmpLE32U, mkexpr(amtT), mkU32(32))),
2017b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               binop(Iop_And32,
2018b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                     binop(Iop_Shr32,
2019b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                           mkexpr(rMt),
2020b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                           mkU8(31)
2021b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                     ),
2022b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                     mkU32(1)
2023ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               ),
2024b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               binop(Iop_And32,
2025b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                     binop(Iop_Shr32,
2026b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                           mkexpr(rMt),
2027b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                           unop(Iop_32to8,
2028b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                binop(Iop_And32,
2029b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                      binop(Iop_Sub32,
2030b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                            mkexpr(amtT),
2031b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                            mkU32(1)),
2032b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                      mkU32(31)
2033b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                )
2034b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                           )
2035b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                     ),
2036b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                     mkU32(1)
2037ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               )
2038ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ),
2039ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            mkexpr(oldC)
2040ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         )
2041ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      );
2042ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2043ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // (Rm >>s (amt <u 32 ? amt : 31))
2044ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign(
2045ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *res,
2046ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      binop(
2047ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         Iop_Sar32,
2048ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         mkexpr(rMt),
2049ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         unop(
2050ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            Iop_32to8,
2051ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            IRExpr_Mux0X(
2052ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               unop(
2053ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 Iop_1Uto8,
2054ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 binop(Iop_CmpLT32U, mkexpr(amtT), mkU32(32))),
2055ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               mkU32(31),
2056ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               mkexpr(amtT)))));
2057ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DIS(buf, "r%u, ASR r%u", rM, rS);
2058ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2059ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2060ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2061ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void compute_result_and_C_after_ROR_by_reg (
2062ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               /*OUT*/HChar* buf,
2063ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               IRTemp* res,
2064ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               IRTemp* newC,
2065ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               IRTemp rMt, IRTemp rSt,  /* operands */
2066ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               UInt rM,    UInt rS      /* only for debug printing */
2067ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            )
2068ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2069ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // rotate right in range 0 .. 255
2070ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // amt = rS & 255
2071ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // shop =  Rm `ror` (amt & 31)
2072ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // shco =  amt == 0 ? oldC : Rm[(amt-1) & 31]
2073ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp amtT = newTemp(Ity_I32);
2074ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign( amtT, binop(Iop_And32, mkexpr(rSt), mkU32(255)) );
2075ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp amt5T = newTemp(Ity_I32);
2076ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign( amt5T, binop(Iop_And32, mkexpr(rSt), mkU32(31)) );
2077ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp oldC = newTemp(Ity_I32);
2078ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign(oldC, mk_armg_calculate_flag_c() );
2079ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (newC) {
2080ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign(
2081ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *newC,
2082ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRExpr_Mux0X(
2083ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            unop(Iop_32to8, mkexpr(amtT)),
2084ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            mkexpr(oldC),
2085ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            binop(Iop_And32,
2086ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  binop(Iop_Shr32,
2087ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        mkexpr(rMt),
2088ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        unop(Iop_32to8,
2089ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             binop(Iop_And32,
2090ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                   binop(Iop_Sub32,
2091ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                         mkexpr(amtT),
2092ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                         mkU32(1)
2093ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                   ),
2094ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                   mkU32(31)
2095ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             )
2096ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        )
2097ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  ),
2098ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  mkU32(1)
2099ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            )
2100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         )
2101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      );
2102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign(
2104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *res,
2105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRExpr_Mux0X(
2106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         unop(Iop_32to8, mkexpr(amt5T)), mkexpr(rMt),
2107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         binop(Iop_Or32,
2108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               binop(Iop_Shr32,
2109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     mkexpr(rMt),
2110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     unop(Iop_32to8, mkexpr(amt5T))
2111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               ),
2112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               binop(Iop_Shl32,
2113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     mkexpr(rMt),
2114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     unop(Iop_32to8,
2115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          binop(Iop_Sub32, mkU32(32), mkexpr(amt5T))
2116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     )
2117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               )
2118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         )
2119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      )
2120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   );
2121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   DIS(buf, "r%u, ROR r#%u", rM, rS);
2122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Generate an expression corresponding to the immediate-shift case of
2126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   a shifter operand.  This is used both for ARM and Thumb2.
2127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Bind it to a temporary, and return that via *res.  If newC is
2129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   non-NULL, also compute a value for the shifter's carry out (in the
2130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   LSB of a word), bind it to a temporary, and return that via *shco.
2131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Generates GETs from the guest state and is therefore not safe to
2133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   use once we start doing PUTs to it, for any given instruction.
2134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   'how' is encoded thusly:
2136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      00b LSL,  01b LSR,  10b ASR,  11b ROR
2137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Most but not all ARM and Thumb integer insns use this encoding.
2138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Be careful to ensure the right value is passed here.
2139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
2140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void compute_result_and_C_after_shift_by_imm5 (
2141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               /*OUT*/HChar* buf,
2142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               /*OUT*/IRTemp* res,
2143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               /*OUT*/IRTemp* newC,
2144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               IRTemp  rMt,       /* reg to shift */
2145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               UInt    how,       /* what kind of shift */
2146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               UInt    shift_amt, /* shift amount (0..31) */
2147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               UInt    rM         /* only for debug printing */
2148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            )
2149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(shift_amt < 32);
2151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(how < 4);
2152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (how) {
2154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0:
2156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         compute_result_and_C_after_LSL_by_imm5(
2157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            buf, res, newC, rMt, shift_amt, rM
2158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         );
2159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
2160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 1:
2162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         compute_result_and_C_after_LSR_by_imm5(
2163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            buf, res, newC, rMt, shift_amt, rM
2164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         );
2165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
2166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 2:
2168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         compute_result_and_C_after_ASR_by_imm5(
2169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            buf, res, newC, rMt, shift_amt, rM
2170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         );
2171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
2172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 3:
2174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (shift_amt == 0) {
2175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            IRTemp oldcT = newTemp(Ity_I32);
2176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            // rotate right 1 bit through carry (?)
2177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            // RRX -- described at ARM ARM A5-17
2178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            // res  = (oldC << 31) | (Rm >>u 1)
2179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            // newC = Rm[0]
2180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (newC) {
2181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               assign( *newC,
2182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       binop(Iop_And32, mkexpr(rMt), mkU32(1)));
2183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
2184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            assign( oldcT, mk_armg_calculate_flag_c() );
2185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            assign( *res,
2186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    binop(Iop_Or32,
2187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          binop(Iop_Shl32, mkexpr(oldcT), mkU8(31)),
2188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          binop(Iop_Shr32, mkexpr(rMt), mkU8(1))) );
2189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            DIS(buf, "r%u, RRX", rM);
2190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
2191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            // rotate right in range 1..31
2192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            // res  = Rm `ror` shift_amt
2193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            // newC = Rm[shift_amt - 1]
2194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vassert(shift_amt >= 1 && shift_amt <= 31);
2195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (newC) {
2196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               assign( *newC,
2197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       binop(Iop_And32,
2198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             binop(Iop_Shr32, mkexpr(rMt),
2199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                              mkU8(shift_amt - 1)),
2200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             mkU32(1)));
2201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
2202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            assign( *res,
2203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    binop(Iop_Or32,
2204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          binop(Iop_Shr32, mkexpr(rMt), mkU8(shift_amt)),
2205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          binop(Iop_Shl32, mkexpr(rMt),
2206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                           mkU8(32-shift_amt))));
2207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            DIS(buf, "r%u, ROR #%u", rM, shift_amt);
2208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
2209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
2210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
2212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /*NOTREACHED*/
2213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(0);
2214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Generate an expression corresponding to the register-shift case of
2219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   a shifter operand.  This is used both for ARM and Thumb2.
2220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Bind it to a temporary, and return that via *res.  If newC is
2222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   non-NULL, also compute a value for the shifter's carry out (in the
2223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   LSB of a word), bind it to a temporary, and return that via *shco.
2224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Generates GETs from the guest state and is therefore not safe to
2226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   use once we start doing PUTs to it, for any given instruction.
2227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   'how' is encoded thusly:
2229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      00b LSL,  01b LSR,  10b ASR,  11b ROR
2230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Most but not all ARM and Thumb integer insns use this encoding.
2231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Be careful to ensure the right value is passed here.
2232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
2233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void compute_result_and_C_after_shift_by_reg (
2234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               /*OUT*/HChar*  buf,
2235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               /*OUT*/IRTemp* res,
2236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               /*OUT*/IRTemp* newC,
2237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               IRTemp  rMt,       /* reg to shift */
2238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               UInt    how,       /* what kind of shift */
2239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               IRTemp  rSt,       /* shift amount */
2240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               UInt    rM,        /* only for debug printing */
2241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               UInt    rS         /* only for debug printing */
2242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            )
2243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(how < 4);
2245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (how) {
2246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0: { /* LSL */
2247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         compute_result_and_C_after_LSL_by_reg(
2248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            buf, res, newC, rMt, rSt, rM, rS
2249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         );
2250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
2251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 1: { /* LSR */
2253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         compute_result_and_C_after_LSR_by_reg(
2254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            buf, res, newC, rMt, rSt, rM, rS
2255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         );
2256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
2257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 2: { /* ASR */
2259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         compute_result_and_C_after_ASR_by_reg(
2260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            buf, res, newC, rMt, rSt, rM, rS
2261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         );
2262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
2263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 3: { /* ROR */
2265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         compute_result_and_C_after_ROR_by_reg(
2266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             buf, res, newC, rMt, rSt, rM, rS
2267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         );
2268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
2269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
2271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /*NOTREACHED*/
2272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(0);
2273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Generate an expression corresponding to a shifter_operand, bind it
2278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   to a temporary, and return that via *shop.  If shco is non-NULL,
2279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   also compute a value for the shifter's carry out (in the LSB of a
2280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   word), bind it to a temporary, and return that via *shco.
2281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   If for some reason we can't come up with a shifter operand (missing
2283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case?  not really a shifter operand?) return False.
2284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Generates GETs from the guest state and is therefore not safe to
2286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   use once we start doing PUTs to it, for any given instruction.
2287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   For ARM insns only; not for Thumb.
2289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
2290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool mk_shifter_operand ( UInt insn_25, UInt insn_11_0,
2291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                 /*OUT*/IRTemp* shop,
2292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                 /*OUT*/IRTemp* shco,
2293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                 /*OUT*/HChar* buf )
2294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt insn_4 = (insn_11_0 >> 4) & 1;
2296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt insn_7 = (insn_11_0 >> 7) & 1;
2297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(insn_25 <= 0x1);
2298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(insn_11_0 <= 0xFFF);
2299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(shop && *shop == IRTemp_INVALID);
2301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   *shop = newTemp(Ity_I32);
2302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (shco) {
2304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert(*shco == IRTemp_INVALID);
2305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *shco = newTemp(Ity_I32);
2306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* 32-bit immediate */
2309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (insn_25 == 1) {
2311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* immediate: (7:0) rotated right by 2 * (11:8) */
2312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt imm = (insn_11_0 >> 0) & 0xFF;
2313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt rot = 2 * ((insn_11_0 >> 8) & 0xF);
2314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert(rot <= 30);
2315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      imm = ROR32(imm, rot);
2316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (shco) {
2317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (rot == 0) {
2318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            assign( *shco, mk_armg_calculate_flag_c() );
2319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
2320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            assign( *shco, mkU32( (imm >> 31) & 1 ) );
2321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
2322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIS(buf, "#0x%x", imm);
2324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( *shop, mkU32(imm) );
2325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return True;
2326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Shift/rotate by immediate */
2329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (insn_25 == 0 && insn_4 == 0) {
2331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Rm (3:0) shifted (6:5) by immediate (11:7) */
2332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt shift_amt = (insn_11_0 >> 7) & 0x1F;
2333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt rM        = (insn_11_0 >> 0) & 0xF;
2334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt how       = (insn_11_0 >> 5) & 3;
2335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* how: 00 = Shl, 01 = Shr, 10 = Sar, 11 = Ror */
2336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp rMt = newTemp(Ity_I32);
2337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign(rMt, getIRegA(rM));
2338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert(shift_amt <= 31);
2340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      compute_result_and_C_after_shift_by_imm5(
2342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         buf, shop, shco, rMt, how, shift_amt, rM
2343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      );
2344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return True;
2345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Shift/rotate by register */
2348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (insn_25 == 0 && insn_4 == 1) {
2349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Rm (3:0) shifted (6:5) by Rs (11:8) */
2350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt rM  = (insn_11_0 >> 0) & 0xF;
2351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt rS  = (insn_11_0 >> 8) & 0xF;
2352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt how = (insn_11_0 >> 5) & 3;
2353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* how: 00 = Shl, 01 = Shr, 10 = Sar, 11 = Ror */
2354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp rMt = newTemp(Ity_I32);
2355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp rSt = newTemp(Ity_I32);
2356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (insn_7 == 1)
2358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return False; /* not really a shifter operand */
2359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign(rMt, getIRegA(rM));
2361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign(rSt, getIRegA(rS));
2362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      compute_result_and_C_after_shift_by_reg(
2364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         buf, shop, shco, rMt, how, rSt, rM, rS
2365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      );
2366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return True;
2367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vex_printf("mk_shifter_operand(0x%x,0x%x)\n", insn_25, insn_11_0 );
2370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return False;
2371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* ARM only */
2375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
2376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownIRExpr* mk_EA_reg_plusminus_imm12 ( UInt rN, UInt bU, UInt imm12,
2377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                    /*OUT*/HChar* buf )
2378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(rN < 16);
2380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(bU < 2);
2381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(imm12 < 0x1000);
2382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar opChar = bU == 1 ? '+' : '-';
2383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   DIS(buf, "[r%u, #%c%u]", rN, opChar, imm12);
2384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return
2385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      binop( (bU == 1 ? Iop_Add32 : Iop_Sub32),
2386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             getIRegA(rN),
2387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             mkU32(imm12) );
2388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* ARM only.
2392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   NB: This is "DecodeImmShift" in newer versions of the the ARM ARM.
2393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
2394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
2395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownIRExpr* mk_EA_reg_plusminus_shifted_reg ( UInt rN, UInt bU, UInt rM,
2396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                          UInt sh2, UInt imm5,
2397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                          /*OUT*/HChar* buf )
2398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(rN < 16);
2400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(bU < 2);
2401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(rM < 16);
2402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(sh2 < 4);
2403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(imm5 < 32);
2404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar   opChar = bU == 1 ? '+' : '-';
2405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRExpr* index  = NULL;
2406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (sh2) {
2407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0: /* LSL */
2408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* imm5 can be in the range 0 .. 31 inclusive. */
2409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         index = binop(Iop_Shl32, getIRegA(rM), mkU8(imm5));
2410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIS(buf, "[r%u, %c r%u LSL #%u]", rN, opChar, rM, imm5);
2411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
2412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 1: /* LSR */
2413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (imm5 == 0) {
2414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            index = mkU32(0);
2415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vassert(0); // ATC
2416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
2417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            index = binop(Iop_Shr32, getIRegA(rM), mkU8(imm5));
2418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
2419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIS(buf, "[r%u, %cr%u, LSR #%u]",
2420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  rN, opChar, rM, imm5 == 0 ? 32 : imm5);
2421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
2422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 2: /* ASR */
2423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Doesn't this just mean that the behaviour with imm5 == 0
2424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            is the same as if it had been 31 ? */
2425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (imm5 == 0) {
2426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            index = binop(Iop_Sar32, getIRegA(rM), mkU8(31));
2427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vassert(0); // ATC
2428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
2429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            index = binop(Iop_Sar32, getIRegA(rM), mkU8(imm5));
2430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
2431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIS(buf, "[r%u, %cr%u, ASR #%u]",
2432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  rN, opChar, rM, imm5 == 0 ? 32 : imm5);
2433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
2434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 3: /* ROR or RRX */
2435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (imm5 == 0) {
2436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            IRTemp rmT    = newTemp(Ity_I32);
2437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            IRTemp cflagT = newTemp(Ity_I32);
2438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            assign(rmT, getIRegA(rM));
2439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            assign(cflagT, mk_armg_calculate_flag_c());
2440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            index = binop(Iop_Or32,
2441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          binop(Iop_Shl32, mkexpr(cflagT), mkU8(31)),
2442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          binop(Iop_Shr32, mkexpr(rmT), mkU8(1)));
2443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            DIS(buf, "[r%u, %cr%u, RRX]", rN, opChar, rM);
2444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
2445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            IRTemp rmT = newTemp(Ity_I32);
2446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            assign(rmT, getIRegA(rM));
2447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vassert(imm5 >= 1 && imm5 <= 31);
2448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            index = binop(Iop_Or32,
2449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          binop(Iop_Shl32, mkexpr(rmT), mkU8(32-imm5)),
2450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          binop(Iop_Shr32, mkexpr(rmT), mkU8(imm5)));
2451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            DIS(buf, "[r%u, %cr%u, ROR #%u]", rN, opChar, rM, imm5);
2452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
2453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
2454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
2455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(0);
2456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(index);
2458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return binop(bU == 1 ? Iop_Add32 : Iop_Sub32,
2459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                getIRegA(rN), index);
2460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* ARM only */
2464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
2465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownIRExpr* mk_EA_reg_plusminus_imm8 ( UInt rN, UInt bU, UInt imm8,
2466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                   /*OUT*/HChar* buf )
2467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(rN < 16);
2469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(bU < 2);
2470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(imm8 < 0x100);
2471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar opChar = bU == 1 ? '+' : '-';
2472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   DIS(buf, "[r%u, #%c%u]", rN, opChar, imm8);
2473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return
2474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      binop( (bU == 1 ? Iop_Add32 : Iop_Sub32),
2475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             getIRegA(rN),
2476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             mkU32(imm8) );
2477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* ARM only */
2481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
2482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownIRExpr* mk_EA_reg_plusminus_reg ( UInt rN, UInt bU, UInt rM,
2483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                  /*OUT*/HChar* buf )
2484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(rN < 16);
2486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(bU < 2);
2487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(rM < 16);
2488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar   opChar = bU == 1 ? '+' : '-';
2489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRExpr* index  = getIRegA(rM);
2490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   DIS(buf, "[r%u, %c r%u]", rN, opChar, rM);
2491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return binop(bU == 1 ? Iop_Add32 : Iop_Sub32,
2492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                getIRegA(rN), index);
2493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* irRes :: Ity_I32 holds a floating point comparison result encoded
2497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   as an IRCmpF64Result.  Generate code to convert it to an
2498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ARM-encoded (N,Z,C,V) group in the lowest 4 bits of an I32 value.
2499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Assign a new temp to hold that value, and return the temp. */
2500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
2501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownIRTemp mk_convert_IRCmpF64Result_to_NZCV ( IRTemp irRes )
2502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp ix       = newTemp(Ity_I32);
2504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp termL    = newTemp(Ity_I32);
2505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp termR    = newTemp(Ity_I32);
2506ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp nzcv     = newTemp(Ity_I32);
2507ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2508ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* This is where the fun starts.  We have to convert 'irRes' from
2509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      an IR-convention return result (IRCmpF64Result) to an
2510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ARM-encoded (N,Z,C,V) group.  The final result is in the bottom
2511ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      4 bits of 'nzcv'. */
2512ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Map compare result from IR to ARM(nzcv) */
2513ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /*
2514ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      FP cmp result | IR   | ARM(nzcv)
2515ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      --------------------------------
2516ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UN              0x45   0011
2517ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      LT              0x01   1000
2518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      GT              0x00   0010
2519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      EQ              0x40   0110
2520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   */
2521ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Now since you're probably wondering WTF ..
2522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2523ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ix fishes the useful bits out of the IR value, bits 6 and 0, and
2524ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      places them side by side, giving a number which is 0, 1, 2 or 3.
2525ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2526ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      termL is a sequence cooked up by GNU superopt.  It converts ix
2527ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         into an almost correct value NZCV value (incredibly), except
2528ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         for the case of UN, where it produces 0100 instead of the
2529ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         required 0011.
2530ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2531ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      termR is therefore a correction term, also computed from ix.  It
2532ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         is 1 in the UN case and 0 for LT, GT and UN.  Hence, to get
2533ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         the final correct value, we subtract termR from termL.
2534ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2535ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Don't take my word for it.  There's a test program at the bottom
2536ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      of this file, to try this out with.
2537ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   */
2538ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign(
2539ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ix,
2540ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      binop(Iop_Or32,
2541ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            binop(Iop_And32,
2542ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  binop(Iop_Shr32, mkexpr(irRes), mkU8(5)),
2543ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  mkU32(3)),
2544ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            binop(Iop_And32, mkexpr(irRes), mkU32(1))));
2545ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2546ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign(
2547ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      termL,
2548ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      binop(Iop_Add32,
2549ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            binop(Iop_Shr32,
2550ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  binop(Iop_Sub32,
2551ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        binop(Iop_Shl32,
2552ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              binop(Iop_Xor32, mkexpr(ix), mkU32(1)),
2553ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              mkU8(30)),
2554ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        mkU32(1)),
2555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  mkU8(29)),
2556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            mkU32(1)));
2557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2558ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign(
2559ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      termR,
2560ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      binop(Iop_And32,
2561ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            binop(Iop_And32,
2562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  mkexpr(ix),
2563ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  binop(Iop_Shr32, mkexpr(ix), mkU8(1))),
2564ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            mkU32(1)));
2565ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2566ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign(nzcv, binop(Iop_Sub32, mkexpr(termL), mkexpr(termR)));
2567ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return nzcv;
2568ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2570ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2571ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Thumb32 only.  This is "ThumbExpandImm" in the ARM ARM.  If
2572ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   updatesC is non-NULL, a boolean is written to it indicating whether
2573ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   or not the C flag is updated, as per ARM ARM "ThumbExpandImm_C".
2574ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
2575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic UInt thumbExpandImm ( Bool* updatesC,
2576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             UInt imm1, UInt imm3, UInt imm8 )
2577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(imm1 < (1<<1));
2579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(imm3 < (1<<3));
2580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(imm8 < (1<<8));
2581ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt i_imm3_a = (imm1 << 4) | (imm3 << 1) | ((imm8 >> 7) & 1);
2582ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt abcdefgh = imm8;
2583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt lbcdefgh = imm8 | 0x80;
2584ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (updatesC) {
2585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *updatesC = i_imm3_a >= 8;
2586ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2587ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (i_imm3_a) {
2588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0: case 1:
2589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return abcdefgh;
2590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 2: case 3:
2591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return (abcdefgh << 16) | abcdefgh;
2592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 4: case 5:
2593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return (abcdefgh << 24) | (abcdefgh << 8);
2594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 6: case 7:
2595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return (abcdefgh << 24) | (abcdefgh << 16)
2596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                | (abcdefgh << 8) | abcdefgh;
2597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 8 ... 31:
2598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return lbcdefgh << (32 - i_imm3_a);
2599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
2600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
2601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2602ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /*NOTREACHED*/vassert(0);
2603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2605ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Version of thumbExpandImm where we simply feed it the
2607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   instruction halfwords (the lowest addressed one is I0). */
2608ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic UInt thumbExpandImm_from_I0_I1 ( Bool* updatesC,
2609ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                        UShort i0s, UShort i1s )
2610ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt i0    = (UInt)i0s;
2612ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt i1    = (UInt)i1s;
2613ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt imm1  = SLICE_UInt(i0,10,10);
2614ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt imm3  = SLICE_UInt(i1,14,12);
2615ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt imm8  = SLICE_UInt(i1,7,0);
2616ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return thumbExpandImm(updatesC, imm1, imm3, imm8);
2617ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2618ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2619ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2620ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Thumb16 only.  Given the firstcond and mask fields from an IT
2621ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   instruction, compute the 32-bit ITSTATE value implied, as described
2622ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   in libvex_guest_arm.h.  This is not the ARM ARM representation.
2623ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Also produce the t/e chars for the 2nd, 3rd, 4th insns, for
2624ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   disassembly printing.  Returns False if firstcond or mask
2625ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   denote something invalid.
2626ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2627ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   The number and conditions for the instructions to be
2628ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   conditionalised depend on firstcond and mask:
2629ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2630ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   mask      cond 1    cond 2      cond 3      cond 4
2631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   1000      fc[3:0]
2633ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   x100      fc[3:0]   fc[3:1]:x
2634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   xy10      fc[3:0]   fc[3:1]:x   fc[3:1]:y
2635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   xyz1      fc[3:0]   fc[3:1]:x   fc[3:1]:y   fc[3:1]:z
2636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   The condition fields are assembled in *itstate backwards (cond 4 at
2638ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   the top, cond 1 at the bottom).  Conditions are << 4'd and then
2639ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ^0xE'd, and those fields that correspond to instructions in the IT
2640ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   block are tagged with a 1 bit.
2641ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
2642ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool compute_ITSTATE ( /*OUT*/UInt*  itstate,
2643ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              /*OUT*/UChar* ch1,
2644ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              /*OUT*/UChar* ch2,
2645ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              /*OUT*/UChar* ch3,
2646ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              UInt firstcond, UInt mask )
2647ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2648ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(firstcond <= 0xF);
2649ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(mask <= 0xF);
2650ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   *itstate = 0;
2651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   *ch1 = *ch2 = *ch3 = '.';
2652ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (mask == 0)
2653ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return False; /* the logic below actually ensures this anyway,
2654ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       but clearer to make it explicit. */
2655ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (firstcond == 0xF)
2656ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return False; /* NV is not allowed */
2657ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (firstcond == 0xE && popcount32(mask) != 1)
2658ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return False; /* if firstcond is AL then all the rest must be too */
2659ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2660ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt m3 = (mask >> 3) & 1;
2661ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt m2 = (mask >> 2) & 1;
2662ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt m1 = (mask >> 1) & 1;
2663ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt m0 = (mask >> 0) & 1;
2664ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2665ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt fc = (firstcond << 4) | 1/*in-IT-block*/;
2666ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt ni = (0xE/*AL*/ << 4) | 0/*not-in-IT-block*/;
2667ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2668ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (m3 == 1 && (m2|m1|m0) == 0) {
2669ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *itstate = (ni << 24) | (ni << 16) | (ni << 8) | fc;
2670ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *itstate ^= 0xE0E0E0E0;
2671ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return True;
2672ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2673ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2674ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (m2 == 1 && (m1|m0) == 0) {
2675ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *itstate = (ni << 24) | (ni << 16) | (setbit32(fc, 4, m3) << 8) | fc;
2676ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *itstate ^= 0xE0E0E0E0;
2677ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *ch1 = m3 == (firstcond & 1) ? 't' : 'e';
2678ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return True;
2679ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2680ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2681ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (m1 == 1 && m0 == 0) {
2682ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *itstate = (ni << 24)
2683ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 | (setbit32(fc, 4, m2) << 16)
2684ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 | (setbit32(fc, 4, m3) << 8) | fc;
2685ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *itstate ^= 0xE0E0E0E0;
2686ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *ch1 = m3 == (firstcond & 1) ? 't' : 'e';
2687ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *ch2 = m2 == (firstcond & 1) ? 't' : 'e';
2688ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return True;
2689ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2690ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2691ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (m0 == 1) {
2692ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *itstate = (setbit32(fc, 4, m1) << 24)
2693ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 | (setbit32(fc, 4, m2) << 16)
2694ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 | (setbit32(fc, 4, m3) << 8) | fc;
2695ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *itstate ^= 0xE0E0E0E0;
2696ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *ch1 = m3 == (firstcond & 1) ? 't' : 'e';
2697ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *ch2 = m2 == (firstcond & 1) ? 't' : 'e';
2698ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *ch3 = m1 == (firstcond & 1) ? 't' : 'e';
2699ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return True;
2700ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2701ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2702ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return False;
2703ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2704ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2705ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2706ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Generate IR to do 32-bit bit reversal, a la Hacker's Delight
2707ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Chapter 7 Section 1. */
2708ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRTemp gen_BITREV ( IRTemp x0 )
2709ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2710ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp x1 = newTemp(Ity_I32);
2711ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp x2 = newTemp(Ity_I32);
2712ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp x3 = newTemp(Ity_I32);
2713ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp x4 = newTemp(Ity_I32);
2714ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp x5 = newTemp(Ity_I32);
2715ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt   c1 = 0x55555555;
2716ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt   c2 = 0x33333333;
2717ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt   c3 = 0x0F0F0F0F;
2718ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt   c4 = 0x00FF00FF;
2719ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt   c5 = 0x0000FFFF;
2720ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign(x1,
2721ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          binop(Iop_Or32,
2722ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                binop(Iop_Shl32,
2723ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      binop(Iop_And32, mkexpr(x0), mkU32(c1)),
2724ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      mkU8(1)),
2725ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                binop(Iop_Shr32,
2726ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      binop(Iop_And32, mkexpr(x0), mkU32(~c1)),
2727ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      mkU8(1))
2728ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ));
2729ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign(x2,
2730ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          binop(Iop_Or32,
2731ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                binop(Iop_Shl32,
2732ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      binop(Iop_And32, mkexpr(x1), mkU32(c2)),
2733ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      mkU8(2)),
2734ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                binop(Iop_Shr32,
2735ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      binop(Iop_And32, mkexpr(x1), mkU32(~c2)),
2736ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      mkU8(2))
2737ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ));
2738ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign(x3,
2739ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          binop(Iop_Or32,
2740ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                binop(Iop_Shl32,
2741ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      binop(Iop_And32, mkexpr(x2), mkU32(c3)),
2742ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      mkU8(4)),
2743ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                binop(Iop_Shr32,
2744ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      binop(Iop_And32, mkexpr(x2), mkU32(~c3)),
2745ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      mkU8(4))
2746ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ));
2747ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign(x4,
2748ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          binop(Iop_Or32,
2749ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                binop(Iop_Shl32,
2750ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      binop(Iop_And32, mkexpr(x3), mkU32(c4)),
2751ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      mkU8(8)),
2752ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                binop(Iop_Shr32,
2753ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      binop(Iop_And32, mkexpr(x3), mkU32(~c4)),
2754ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      mkU8(8))
2755ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ));
2756ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign(x5,
2757ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          binop(Iop_Or32,
2758ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                binop(Iop_Shl32,
2759ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      binop(Iop_And32, mkexpr(x4), mkU32(c5)),
2760ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      mkU8(16)),
2761ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                binop(Iop_Shr32,
2762ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      binop(Iop_And32, mkexpr(x4), mkU32(~c5)),
2763ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      mkU8(16))
2764ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ));
2765ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return x5;
2766ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2767ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2768ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2769ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Generate IR to do rearrange bytes 3:2:1:0 in a word in to the order
2770ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   0:1:2:3 (aka byte-swap). */
2771ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRTemp gen_REV ( IRTemp arg )
2772ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2773ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp res = newTemp(Ity_I32);
2774ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign(res,
2775ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          binop(Iop_Or32,
2776ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                binop(Iop_Shl32, mkexpr(arg), mkU8(24)),
2777ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          binop(Iop_Or32,
2778ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                binop(Iop_And32, binop(Iop_Shl32, mkexpr(arg), mkU8(8)),
2779ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                 mkU32(0x00FF0000)),
2780ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          binop(Iop_Or32,
2781ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                binop(Iop_And32, binop(Iop_Shr32, mkexpr(arg), mkU8(8)),
2782ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                       mkU32(0x0000FF00)),
2783ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                binop(Iop_And32, binop(Iop_Shr32, mkexpr(arg), mkU8(24)),
2784ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                       mkU32(0x000000FF) )
2785ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ))));
2786ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return res;
2787ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2788ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2789ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2790ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Generate IR to do rearrange bytes 3:2:1:0 in a word in to the order
2791ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   2:3:0:1 (swap within lo and hi halves). */
2792ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRTemp gen_REV16 ( IRTemp arg )
2793ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2794ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp res = newTemp(Ity_I32);
2795ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign(res,
2796ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          binop(Iop_Or32,
2797ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                binop(Iop_And32,
2798ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      binop(Iop_Shl32, mkexpr(arg), mkU8(8)),
2799ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      mkU32(0xFF00FF00)),
2800ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                binop(Iop_And32,
2801ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      binop(Iop_Shr32, mkexpr(arg), mkU8(8)),
2802ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      mkU32(0x00FF00FF))));
2803ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return res;
2804ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2805ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2806ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2807ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
2808ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Advanced SIMD (NEON) instructions                    ---*/
2809ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
2810ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2811ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
2812ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- NEON data processing                                 ---*/
2813ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
2814ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2815ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* For all NEON DP ops, we use the normal scheme to handle conditional
2816ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   writes to registers -- pass in condT and hand that on to the
2817ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   put*Reg functions.  In ARM mode condT is always IRTemp_INVALID
2818ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   since NEON is unconditional for ARM.  In Thumb mode condT is
2819ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   derived from the ITSTATE shift register in the normal way. */
2820ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2821ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
2822ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownUInt get_neon_d_regno(UInt theInstr)
2823ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2824ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt x = ((theInstr >> 18) & 0x10) | ((theInstr >> 12) & 0xF);
2825ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (theInstr & 0x40) {
2826ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (x & 1) {
2827ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         x = x + 0x100;
2828ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else {
2829ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         x = x >> 1;
2830ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2831ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2832ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return x;
2833ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2834ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2835ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
2836ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownUInt get_neon_n_regno(UInt theInstr)
2837ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2838ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt x = ((theInstr >> 3) & 0x10) | ((theInstr >> 16) & 0xF);
2839ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (theInstr & 0x40) {
2840ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (x & 1) {
2841ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         x = x + 0x100;
2842ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else {
2843ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         x = x >> 1;
2844ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2845ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2846ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return x;
2847ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2848ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2849ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
2850ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownUInt get_neon_m_regno(UInt theInstr)
2851ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2852ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt x = ((theInstr >> 1) & 0x10) | (theInstr & 0xF);
2853ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (theInstr & 0x40) {
2854ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (x & 1) {
2855ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         x = x + 0x100;
2856ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else {
2857ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         x = x >> 1;
2858ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2859ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2860ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return x;
2861ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2862ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2863ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
2864ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownBool dis_neon_vext ( UInt theInstr, IRTemp condT )
2865ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2866ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt dreg = get_neon_d_regno(theInstr);
2867ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt mreg = get_neon_m_regno(theInstr);
2868ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt nreg = get_neon_n_regno(theInstr);
2869ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt imm4 = (theInstr >> 8) & 0xf;
2870ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt Q = (theInstr >> 6) & 1;
2871ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   HChar reg_t = Q ? 'q' : 'd';
2872ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2873ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (Q) {
2874ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putQReg(dreg, triop(Iop_ExtractV128, getQReg(nreg),
2875ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               getQReg(mreg), mkU8(imm4)), condT);
2876ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
2877ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putDRegI64(dreg, triop(Iop_Extract64, getDRegI64(nreg),
2878ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 getDRegI64(mreg), mkU8(imm4)), condT);
2879ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2880ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   DIP("vext.8 %c%d, %c%d, %c%d, #%d\n", reg_t, dreg, reg_t, nreg,
2881ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                         reg_t, mreg, imm4);
2882ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return True;
2883ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2884ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2885ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* VTBL, VTBX */
2886ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
2887ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownBool dis_neon_vtb ( UInt theInstr, IRTemp condT )
2888ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2889ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt op = (theInstr >> 6) & 1;
2890ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt dreg = get_neon_d_regno(theInstr & ~(1 << 6));
2891ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt nreg = get_neon_n_regno(theInstr & ~(1 << 6));
2892ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt mreg = get_neon_m_regno(theInstr & ~(1 << 6));
2893ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt len = (theInstr >> 8) & 3;
2894ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int i;
2895ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IROp cmp;
2896ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ULong imm;
2897ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp arg_l;
2898ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp old_mask, new_mask, cur_mask;
2899ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp old_res, new_res;
2900ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp old_arg, new_arg;
2901ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2902ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (dreg >= 0x100 || mreg >= 0x100 || nreg >= 0x100)
2903ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return False;
2904ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (nreg + len > 31)
2905ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return False;
2906ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2907ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   cmp = Iop_CmpGT8Ux8;
2908ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2909ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   old_mask = newTemp(Ity_I64);
2910ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   old_res = newTemp(Ity_I64);
2911ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   old_arg = newTemp(Ity_I64);
2912ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign(old_mask, mkU64(0));
2913ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign(old_res, mkU64(0));
2914ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign(old_arg, getDRegI64(mreg));
2915ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   imm = 8;
2916ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   imm = (imm <<  8) | imm;
2917ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   imm = (imm << 16) | imm;
2918ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   imm = (imm << 32) | imm;
2919ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2920ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (i = 0; i <= len; i++) {
2921ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      arg_l = newTemp(Ity_I64);
2922ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      new_mask = newTemp(Ity_I64);
2923ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      cur_mask = newTemp(Ity_I64);
2924ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      new_res = newTemp(Ity_I64);
2925ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      new_arg = newTemp(Ity_I64);
2926ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign(arg_l, getDRegI64(nreg+i));
2927ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign(new_arg, binop(Iop_Sub8x8, mkexpr(old_arg), mkU64(imm)));
2928ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign(cur_mask, binop(cmp, mkU64(imm), mkexpr(old_arg)));
2929ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign(new_mask, binop(Iop_Or64, mkexpr(old_mask), mkexpr(cur_mask)));
2930ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign(new_res, binop(Iop_Or64,
2931ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            mkexpr(old_res),
2932ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            binop(Iop_And64,
2933ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                  binop(Iop_Perm8x8,
2934ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                        mkexpr(arg_l),
2935ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                        binop(Iop_And64,
2936ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                              mkexpr(old_arg),
2937ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                              mkexpr(cur_mask))),
2938ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                  mkexpr(cur_mask))));
2939ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2940ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      old_arg = new_arg;
2941ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      old_mask = new_mask;
2942ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      old_res = new_res;
2943ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2944ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (op) {
2945ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      new_res = newTemp(Ity_I64);
2946ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign(new_res, binop(Iop_Or64,
2947ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            binop(Iop_And64,
2948ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                  getDRegI64(dreg),
2949ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                  unop(Iop_Not64, mkexpr(old_mask))),
2950ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            mkexpr(old_res)));
2951ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      old_res = new_res;
2952ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2953ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2954ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   putDRegI64(dreg, mkexpr(old_res), condT);
2955ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   DIP("vtb%c.8 d%u, {", op ? 'x' : 'l', dreg);
2956ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (len > 0) {
2957ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("d%u-d%u", nreg, nreg + len);
2958ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
2959ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("d%u", nreg);
2960ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2961ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   DIP("}, d%u\n", mreg);
2962ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return True;
2963ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2964ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2965ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* VDUP (scalar)  */
2966ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
2967ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownBool dis_neon_vdup ( UInt theInstr, IRTemp condT )
2968ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2969ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt Q = (theInstr >> 6) & 1;
2970ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt dreg = ((theInstr >> 18) & 0x10) | ((theInstr >> 12) & 0xF);
2971ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt mreg = ((theInstr >> 1) & 0x10) | (theInstr & 0xF);
2972ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt imm4 = (theInstr >> 16) & 0xF;
2973ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt index;
2974ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt size;
2975ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp arg_m;
2976ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp res;
2977ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IROp op, op2;
2978ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2979ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if ((imm4 == 0) || (imm4 == 8))
2980ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return False;
2981ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if ((Q == 1) && ((dreg & 1) == 1))
2982ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return False;
2983ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (Q)
2984ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      dreg >>= 1;
2985ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   arg_m = newTemp(Ity_I64);
2986ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign(arg_m, getDRegI64(mreg));
2987ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (Q)
2988ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      res = newTemp(Ity_V128);
2989ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   else
2990ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      res = newTemp(Ity_I64);
2991ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if ((imm4 & 1) == 1) {
2992ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      op = Q ? Iop_Dup8x16 : Iop_Dup8x8;
2993ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      op2 = Iop_GetElem8x8;
2994ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      index = imm4 >> 1;
2995ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      size = 8;
2996ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else if ((imm4 & 3) == 2) {
2997ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      op = Q ? Iop_Dup16x8 : Iop_Dup16x4;
2998ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      op2 = Iop_GetElem16x4;
2999ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      index = imm4 >> 2;
3000ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      size = 16;
3001ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else if ((imm4 & 7) == 4) {
3002ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      op = Q ? Iop_Dup32x4 : Iop_Dup32x2;
3003ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      op2 = Iop_GetElem32x2;
3004ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      index = imm4 >> 3;
3005ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      size = 32;
3006ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
3007ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return False; // can this ever happen?
3008ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3009ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign(res, unop(op, binop(op2, mkexpr(arg_m), mkU8(index))));
3010ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (Q) {
3011ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putQReg(dreg, mkexpr(res), condT);
3012ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
3013ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putDRegI64(dreg, mkexpr(res), condT);
3014ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3015ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   DIP("vdup.%d %c%d, d%d[%d]\n", size, Q ? 'q' : 'd', dreg, mreg, index);
3016ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return True;
3017ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3018ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3019ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* A7.4.1 Three registers of the same length */
3020ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
3021ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownBool dis_neon_data_3same ( UInt theInstr, IRTemp condT )
3022ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
3023ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt Q = (theInstr >> 6) & 1;
3024ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt dreg = get_neon_d_regno(theInstr);
3025ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt nreg = get_neon_n_regno(theInstr);
3026ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt mreg = get_neon_m_regno(theInstr);
3027ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt A = (theInstr >> 8) & 0xF;
3028ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt B = (theInstr >> 4) & 1;
3029ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt C = (theInstr >> 20) & 0x3;
3030ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt U = (theInstr >> 24) & 1;
3031ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt size = C;
3032ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3033ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp arg_n;
3034ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp arg_m;
3035ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp res;
3036ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3037ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (Q) {
3038ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      arg_n = newTemp(Ity_V128);
3039ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      arg_m = newTemp(Ity_V128);
3040ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      res = newTemp(Ity_V128);
3041ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign(arg_n, getQReg(nreg));
3042ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign(arg_m, getQReg(mreg));
3043ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
3044ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      arg_n = newTemp(Ity_I64);
3045ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      arg_m = newTemp(Ity_I64);
3046ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      res = newTemp(Ity_I64);
3047ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign(arg_n, getDRegI64(nreg));
3048ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign(arg_m, getDRegI64(mreg));
3049ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3050ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3051ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch(A) {
3052ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0:
3053ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (B == 0) {
3054ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* VHADD */
3055ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ULong imm = 0;
3056ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            IRExpr *imm_val;
3057ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            IROp addOp;
3058ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            IROp andOp;
3059ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            IROp shOp;
3060ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            char regType = Q ? 'q' : 'd';
3061ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3062ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (size == 3)
3063ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               return False;
3064ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            switch(size) {
3065ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               case 0: imm = 0x101010101010101LL; break;
3066ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               case 1: imm = 0x1000100010001LL; break;
3067ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               case 2: imm = 0x100000001LL; break;
3068ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               default: vassert(0);
3069ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
3070ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (Q) {
3071ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               imm_val = binop(Iop_64HLtoV128, mkU64(imm), mkU64(imm));
3072ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               andOp = Iop_AndV128;
3073ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else {
3074ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               imm_val = mkU64(imm);
3075ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               andOp = Iop_And64;
3076ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
3077ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (U) {
3078ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               switch(size) {
3079ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 0:
3080ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     addOp = Q ? Iop_Add8x16 : Iop_Add8x8;
3081ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     shOp = Q ? Iop_ShrN8x16 : Iop_ShrN8x8;
3082ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     break;
3083ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 1:
3084ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     addOp = Q ? Iop_Add16x8 : Iop_Add16x4;
3085ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     shOp = Q ? Iop_ShrN16x8 : Iop_ShrN16x4;
3086ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     break;
3087ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 2:
3088ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     addOp = Q ? Iop_Add32x4 : Iop_Add32x2;
3089ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     shOp = Q ? Iop_ShrN32x4 : Iop_ShrN32x2;
3090ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     break;
3091ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  default:
3092ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     vassert(0);
3093ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               }
3094ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else {
3095ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               switch(size) {
3096ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 0:
3097ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     addOp = Q ? Iop_Add8x16 : Iop_Add8x8;
3098ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     shOp = Q ? Iop_SarN8x16 : Iop_SarN8x8;
3099ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     break;
3100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 1:
3101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     addOp = Q ? Iop_Add16x8 : Iop_Add16x4;
3102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     shOp = Q ? Iop_SarN16x8 : Iop_SarN16x4;
3103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     break;
3104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 2:
3105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     addOp = Q ? Iop_Add32x4 : Iop_Add32x2;
3106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     shOp = Q ? Iop_SarN32x4 : Iop_SarN32x2;
3107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     break;
3108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  default:
3109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     vassert(0);
3110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               }
3111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
3112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            assign(res,
3113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   binop(addOp,
3114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         binop(addOp,
3115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               binop(shOp, mkexpr(arg_m), mkU8(1)),
3116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               binop(shOp, mkexpr(arg_n), mkU8(1))),
3117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         binop(shOp,
3118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               binop(addOp,
3119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                     binop(andOp, mkexpr(arg_m), imm_val),
3120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                     binop(andOp, mkexpr(arg_n), imm_val)),
3121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               mkU8(1))));
3122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            DIP("vhadd.%c%d %c%d, %c%d, %c%d\n",
3123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                U ? 'u' : 's', 8 << size, regType,
3124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                dreg, regType, nreg, regType, mreg);
3125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
3126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* VQADD */
3127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            IROp op, op2;
3128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            IRTemp tmp;
3129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            char reg_t = Q ? 'q' : 'd';
3130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (Q) {
3131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               switch (size) {
3132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 0:
3133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op = U ? Iop_QAdd8Ux16 : Iop_QAdd8Sx16;
3134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op2 = Iop_Add8x16;
3135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     break;
3136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 1:
3137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op = U ? Iop_QAdd16Ux8 : Iop_QAdd16Sx8;
3138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op2 = Iop_Add16x8;
3139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     break;
3140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 2:
3141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op = U ? Iop_QAdd32Ux4 : Iop_QAdd32Sx4;
3142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op2 = Iop_Add32x4;
3143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     break;
3144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 3:
3145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op = U ? Iop_QAdd64Ux2 : Iop_QAdd64Sx2;
3146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op2 = Iop_Add64x2;
3147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     break;
3148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  default:
3149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     vassert(0);
3150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               }
3151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else {
3152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               switch (size) {
3153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 0:
3154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op = U ? Iop_QAdd8Ux8 : Iop_QAdd8Sx8;
3155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op2 = Iop_Add8x8;
3156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     break;
3157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 1:
3158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op = U ? Iop_QAdd16Ux4 : Iop_QAdd16Sx4;
3159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op2 = Iop_Add16x4;
3160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     break;
3161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 2:
3162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op = U ? Iop_QAdd32Ux2 : Iop_QAdd32Sx2;
3163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op2 = Iop_Add32x2;
3164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     break;
3165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 3:
3166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op = U ? Iop_QAdd64Ux1 : Iop_QAdd64Sx1;
3167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op2 = Iop_Add64;
3168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     break;
3169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  default:
3170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     vassert(0);
3171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               }
3172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
3173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (Q) {
3174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               tmp = newTemp(Ity_V128);
3175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else {
3176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               tmp = newTemp(Ity_I64);
3177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
3178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m)));
3179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#ifndef DISABLE_QC_FLAG
3180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            assign(tmp, binop(op2, mkexpr(arg_n), mkexpr(arg_m)));
3181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            setFlag_QC(mkexpr(res), mkexpr(tmp), Q, condT);
3182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
3183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            DIP("vqadd.%c%d %c%d, %c%d, %c%d\n",
3184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                U ? 'u' : 's',
3185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                8 << size, reg_t, dreg, reg_t, nreg, reg_t, mreg);
3186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
3187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
3188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 1:
3189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (B == 0) {
3190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* VRHADD */
3191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* VRHADD C, A, B ::=
3192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 C = (A >> 1) + (B >> 1) + (((A & 1) + (B & 1) + 1) >> 1) */
3193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            IROp shift_op, add_op;
3194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            IRTemp cc;
3195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ULong one = 1;
3196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HChar reg_t = Q ? 'q' : 'd';
3197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            switch (size) {
3198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               case 0: one = (one <<  8) | one; /* fall through */
3199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               case 1: one = (one << 16) | one; /* fall through */
3200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               case 2: one = (one << 32) | one; break;
3201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               case 3: return False;
3202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               default: vassert(0);
3203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
3204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (Q) {
3205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               switch (size) {
3206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 0:
3207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     shift_op = U ? Iop_ShrN8x16 : Iop_SarN8x16;
3208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     add_op = Iop_Add8x16;
3209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     break;
3210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 1:
3211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     shift_op = U ? Iop_ShrN16x8 : Iop_SarN16x8;
3212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     add_op = Iop_Add16x8;
3213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     break;
3214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 2:
3215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     shift_op = U ? Iop_ShrN32x4 : Iop_SarN32x4;
3216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     add_op = Iop_Add32x4;
3217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     break;
3218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 3:
3219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     return False;
3220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  default:
3221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     vassert(0);
3222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               }
3223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else {
3224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               switch (size) {
3225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 0:
3226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     shift_op = U ? Iop_ShrN8x8 : Iop_SarN8x8;
3227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     add_op = Iop_Add8x8;
3228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     break;
3229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 1:
3230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     shift_op = U ? Iop_ShrN16x4 : Iop_SarN16x4;
3231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     add_op = Iop_Add16x4;
3232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     break;
3233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 2:
3234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     shift_op = U ? Iop_ShrN32x2 : Iop_SarN32x2;
3235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     add_op = Iop_Add32x2;
3236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     break;
3237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 3:
3238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     return False;
3239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  default:
3240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     vassert(0);
3241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               }
3242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
3243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (Q) {
3244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               cc = newTemp(Ity_V128);
3245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               assign(cc, binop(shift_op,
3246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                binop(add_op,
3247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                      binop(add_op,
3248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                            binop(Iop_AndV128,
3249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                                  mkexpr(arg_n),
3250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                                  binop(Iop_64HLtoV128,
3251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                                        mkU64(one),
3252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                                        mkU64(one))),
3253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                            binop(Iop_AndV128,
3254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                                  mkexpr(arg_m),
3255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                                  binop(Iop_64HLtoV128,
3256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                                        mkU64(one),
3257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                                        mkU64(one)))),
3258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                      binop(Iop_64HLtoV128,
3259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                            mkU64(one),
3260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                            mkU64(one))),
3261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                mkU8(1)));
3262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               assign(res, binop(add_op,
3263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                 binop(add_op,
3264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                       binop(shift_op,
3265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                             mkexpr(arg_n),
3266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                             mkU8(1)),
3267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                       binop(shift_op,
3268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                             mkexpr(arg_m),
3269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                             mkU8(1))),
3270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                 mkexpr(cc)));
3271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else {
3272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               cc = newTemp(Ity_I64);
3273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               assign(cc, binop(shift_op,
3274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                binop(add_op,
3275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                      binop(add_op,
3276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                            binop(Iop_And64,
3277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                                  mkexpr(arg_n),
3278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                                  mkU64(one)),
3279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                            binop(Iop_And64,
3280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                                  mkexpr(arg_m),
3281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                                  mkU64(one))),
3282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                      mkU64(one)),
3283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                mkU8(1)));
3284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               assign(res, binop(add_op,
3285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                 binop(add_op,
3286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                       binop(shift_op,
3287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                             mkexpr(arg_n),
3288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                             mkU8(1)),
3289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                       binop(shift_op,
3290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                             mkexpr(arg_m),
3291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                             mkU8(1))),
3292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                 mkexpr(cc)));
3293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
3294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            DIP("vrhadd.%c%d %c%d, %c%d, %c%d\n",
3295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                U ? 'u' : 's',
3296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                8 << size, reg_t, dreg, reg_t, nreg, reg_t, mreg);
3297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
3298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (U == 0)  {
3299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               switch(C) {
3300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 0: {
3301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     /* VAND  */
3302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     HChar reg_t = Q ? 'q' : 'd';
3303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     if (Q) {
3304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        assign(res, binop(Iop_AndV128, mkexpr(arg_n),
3305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                                       mkexpr(arg_m)));
3306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     } else {
3307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        assign(res, binop(Iop_And64, mkexpr(arg_n),
3308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                                     mkexpr(arg_m)));
3309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     }
3310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     DIP("vand %c%d, %c%d, %c%d\n",
3311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         reg_t, dreg, reg_t, nreg, reg_t, mreg);
3312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     break;
3313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  }
3314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 1: {
3315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     /* VBIC  */
3316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     HChar reg_t = Q ? 'q' : 'd';
3317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     if (Q) {
3318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        assign(res, binop(Iop_AndV128,mkexpr(arg_n),
3319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               unop(Iop_NotV128, mkexpr(arg_m))));
3320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     } else {
3321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        assign(res, binop(Iop_And64, mkexpr(arg_n),
3322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               unop(Iop_Not64, mkexpr(arg_m))));
3323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     }
3324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     DIP("vbic %c%d, %c%d, %c%d\n",
3325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         reg_t, dreg, reg_t, nreg, reg_t, mreg);
3326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     break;
3327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  }
3328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 2:
3329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     if ( nreg != mreg) {
3330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        /* VORR  */
3331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        HChar reg_t = Q ? 'q' : 'd';
3332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        if (Q) {
3333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           assign(res, binop(Iop_OrV128, mkexpr(arg_n),
3334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                                         mkexpr(arg_m)));
3335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        } else {
3336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           assign(res, binop(Iop_Or64, mkexpr(arg_n),
3337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                                       mkexpr(arg_m)));
3338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        }
3339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        DIP("vorr %c%d, %c%d, %c%d\n",
3340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            reg_t, dreg, reg_t, nreg, reg_t, mreg);
3341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     } else {
3342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        /* VMOV  */
3343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        HChar reg_t = Q ? 'q' : 'd';
3344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        assign(res, mkexpr(arg_m));
3345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        DIP("vmov %c%d, %c%d\n", reg_t, dreg, reg_t, mreg);
3346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     }
3347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     break;
3348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 3:{
3349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     /* VORN  */
3350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     HChar reg_t = Q ? 'q' : 'd';
3351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     if (Q) {
3352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        assign(res, binop(Iop_OrV128,mkexpr(arg_n),
3353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               unop(Iop_NotV128, mkexpr(arg_m))));
3354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     } else {
3355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        assign(res, binop(Iop_Or64, mkexpr(arg_n),
3356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               unop(Iop_Not64, mkexpr(arg_m))));
3357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     }
3358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     DIP("vorn %c%d, %c%d, %c%d\n",
3359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         reg_t, dreg, reg_t, nreg, reg_t, mreg);
3360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     break;
3361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  }
3362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               }
3363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else {
3364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               switch(C) {
3365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 0:
3366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     /* VEOR (XOR)  */
3367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     if (Q) {
3368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        assign(res, binop(Iop_XorV128, mkexpr(arg_n),
3369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                                       mkexpr(arg_m)));
3370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     } else {
3371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        assign(res, binop(Iop_Xor64, mkexpr(arg_n),
3372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                                     mkexpr(arg_m)));
3373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     }
3374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     DIP("veor %c%u, %c%u, %c%u\n", Q ? 'q' : 'd', dreg,
3375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg);
3376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     break;
3377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 1:
3378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     /* VBSL  */
3379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     if (Q) {
3380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        IRTemp reg_d = newTemp(Ity_V128);
3381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        assign(reg_d, getQReg(dreg));
3382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        assign(res,
3383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               binop(Iop_OrV128,
3384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                     binop(Iop_AndV128, mkexpr(arg_n),
3385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                                        mkexpr(reg_d)),
3386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                     binop(Iop_AndV128,
3387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                           mkexpr(arg_m),
3388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                           unop(Iop_NotV128,
3389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                                 mkexpr(reg_d)) ) ) );
3390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     } else {
3391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        IRTemp reg_d = newTemp(Ity_I64);
3392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        assign(reg_d, getDRegI64(dreg));
3393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        assign(res,
3394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               binop(Iop_Or64,
3395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                     binop(Iop_And64, mkexpr(arg_n),
3396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                                      mkexpr(reg_d)),
3397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                     binop(Iop_And64,
3398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                           mkexpr(arg_m),
3399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                           unop(Iop_Not64, mkexpr(reg_d)))));
3400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     }
3401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     DIP("vbsl %c%u, %c%u, %c%u\n",
3402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         Q ? 'q' : 'd', dreg,
3403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg);
3404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     break;
3405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 2:
3406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     /* VBIT  */
3407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     if (Q) {
3408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        IRTemp reg_d = newTemp(Ity_V128);
3409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        assign(reg_d, getQReg(dreg));
3410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        assign(res,
3411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               binop(Iop_OrV128,
3412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                     binop(Iop_AndV128, mkexpr(arg_n),
3413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                                        mkexpr(arg_m)),
3414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                     binop(Iop_AndV128,
3415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                           mkexpr(reg_d),
3416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                           unop(Iop_NotV128, mkexpr(arg_m)))));
3417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     } else {
3418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        IRTemp reg_d = newTemp(Ity_I64);
3419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        assign(reg_d, getDRegI64(dreg));
3420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        assign(res,
3421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               binop(Iop_Or64,
3422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                     binop(Iop_And64, mkexpr(arg_n),
3423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                                      mkexpr(arg_m)),
3424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                     binop(Iop_And64,
3425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                           mkexpr(reg_d),
3426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                           unop(Iop_Not64, mkexpr(arg_m)))));
3427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     }
3428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     DIP("vbit %c%u, %c%u, %c%u\n",
3429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         Q ? 'q' : 'd', dreg,
3430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg);
3431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     break;
3432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 3:
3433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     /* VBIF  */
3434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     if (Q) {
3435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        IRTemp reg_d = newTemp(Ity_V128);
3436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        assign(reg_d, getQReg(dreg));
3437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        assign(res,
3438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               binop(Iop_OrV128,
3439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                     binop(Iop_AndV128, mkexpr(reg_d),
3440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                                        mkexpr(arg_m)),
3441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                     binop(Iop_AndV128,
3442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                           mkexpr(arg_n),
3443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                           unop(Iop_NotV128, mkexpr(arg_m)))));
3444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     } else {
3445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        IRTemp reg_d = newTemp(Ity_I64);
3446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        assign(reg_d, getDRegI64(dreg));
3447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        assign(res,
3448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               binop(Iop_Or64,
3449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                     binop(Iop_And64, mkexpr(reg_d),
3450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                                      mkexpr(arg_m)),
3451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                     binop(Iop_And64,
3452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                           mkexpr(arg_n),
3453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                           unop(Iop_Not64, mkexpr(arg_m)))));
3454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     }
3455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     DIP("vbif %c%u, %c%u, %c%u\n",
3456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         Q ? 'q' : 'd', dreg,
3457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg);
3458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     break;
3459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               }
3460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
3461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
3462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
3463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 2:
3464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (B == 0) {
3465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* VHSUB */
3466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* (A >> 1) - (B >> 1) - (NOT (A) & B & 1)   */
3467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ULong imm = 0;
3468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            IRExpr *imm_val;
3469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            IROp subOp;
3470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            IROp notOp;
3471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            IROp andOp;
3472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            IROp shOp;
3473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (size == 3)
3474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               return False;
3475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            switch(size) {
3476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               case 0: imm = 0x101010101010101LL; break;
3477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               case 1: imm = 0x1000100010001LL; break;
3478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               case 2: imm = 0x100000001LL; break;
3479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               default: vassert(0);
3480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
3481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (Q) {
3482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               imm_val = binop(Iop_64HLtoV128, mkU64(imm), mkU64(imm));
3483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               andOp = Iop_AndV128;
3484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               notOp = Iop_NotV128;
3485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else {
3486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               imm_val = mkU64(imm);
3487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               andOp = Iop_And64;
3488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               notOp = Iop_Not64;
3489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
3490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (U) {
3491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               switch(size) {
3492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 0:
3493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     subOp = Q ? Iop_Sub8x16 : Iop_Sub8x8;
3494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     shOp = Q ? Iop_ShrN8x16 : Iop_ShrN8x8;
3495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     break;
3496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 1:
3497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     subOp = Q ? Iop_Sub16x8 : Iop_Sub16x4;
3498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     shOp = Q ? Iop_ShrN16x8 : Iop_ShrN16x4;
3499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     break;
3500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 2:
3501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     subOp = Q ? Iop_Sub32x4 : Iop_Sub32x2;
3502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     shOp = Q ? Iop_ShrN32x4 : Iop_ShrN32x2;
3503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     break;
3504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  default:
3505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     vassert(0);
3506ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               }
3507ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else {
3508ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               switch(size) {
3509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 0:
3510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     subOp = Q ? Iop_Sub8x16 : Iop_Sub8x8;
3511ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     shOp = Q ? Iop_SarN8x16 : Iop_SarN8x8;
3512ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     break;
3513ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 1:
3514ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     subOp = Q ? Iop_Sub16x8 : Iop_Sub16x4;
3515ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     shOp = Q ? Iop_SarN16x8 : Iop_SarN16x4;
3516ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     break;
3517ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 2:
3518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     subOp = Q ? Iop_Sub32x4 : Iop_Sub32x2;
3519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     shOp = Q ? Iop_SarN32x4 : Iop_SarN32x2;
3520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     break;
3521ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  default:
3522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     vassert(0);
3523ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               }
3524ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
3525ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            assign(res,
3526ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   binop(subOp,
3527ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         binop(subOp,
3528ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               binop(shOp, mkexpr(arg_n), mkU8(1)),
3529ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               binop(shOp, mkexpr(arg_m), mkU8(1))),
3530ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         binop(andOp,
3531ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               binop(andOp,
3532ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                     unop(notOp, mkexpr(arg_n)),
3533ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                     mkexpr(arg_m)),
3534ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               imm_val)));
3535ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            DIP("vhsub.%c%u %c%u, %c%u, %c%u\n",
3536ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                U ? 'u' : 's', 8 << size,
3537ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', nreg, Q ? 'q' : 'd',
3538ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                mreg);
3539ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
3540ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* VQSUB */
3541ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            IROp op, op2;
3542ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            IRTemp tmp;
3543ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (Q) {
3544ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               switch (size) {
3545ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 0:
3546ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op = U ? Iop_QSub8Ux16 : Iop_QSub8Sx16;
3547ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op2 = Iop_Sub8x16;
3548ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     break;
3549ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 1:
3550ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op = U ? Iop_QSub16Ux8 : Iop_QSub16Sx8;
3551ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op2 = Iop_Sub16x8;
3552ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     break;
3553ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 2:
3554ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op = U ? Iop_QSub32Ux4 : Iop_QSub32Sx4;
3555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op2 = Iop_Sub32x4;
3556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     break;
3557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 3:
3558ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op = U ? Iop_QSub64Ux2 : Iop_QSub64Sx2;
3559ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op2 = Iop_Sub64x2;
3560ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     break;
3561ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  default:
3562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     vassert(0);
3563ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               }
3564ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else {
3565ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               switch (size) {
3566ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 0:
3567ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op = U ? Iop_QSub8Ux8 : Iop_QSub8Sx8;
3568ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op2 = Iop_Sub8x8;
3569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     break;
3570ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 1:
3571ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op = U ? Iop_QSub16Ux4 : Iop_QSub16Sx4;
3572ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op2 = Iop_Sub16x4;
3573ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     break;
3574ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 2:
3575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op = U ? Iop_QSub32Ux2 : Iop_QSub32Sx2;
3576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op2 = Iop_Sub32x2;
3577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     break;
3578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 3:
3579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op = U ? Iop_QSub64Ux1 : Iop_QSub64Sx1;
3580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op2 = Iop_Sub64;
3581ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     break;
3582ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  default:
3583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     vassert(0);
3584ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               }
3585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
3586ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (Q)
3587ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               tmp = newTemp(Ity_V128);
3588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            else
3589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               tmp = newTemp(Ity_I64);
3590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m)));
3591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#ifndef DISABLE_QC_FLAG
3592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            assign(tmp, binop(op2, mkexpr(arg_n), mkexpr(arg_m)));
3593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            setFlag_QC(mkexpr(res), mkexpr(tmp), Q, condT);
3594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
3595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            DIP("vqsub.%c%u %c%u, %c%u, %c%u\n",
3596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                U ? 'u' : 's', 8 << size,
3597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', nreg, Q ? 'q' : 'd',
3598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                mreg);
3599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
3600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
3601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 3: {
3602ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            IROp op;
3603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (Q) {
3604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               switch (size) {
3605ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 0: op = U ? Iop_CmpGT8Ux16 : Iop_CmpGT8Sx16; break;
3606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 1: op = U ? Iop_CmpGT16Ux8 : Iop_CmpGT16Sx8; break;
3607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 2: op = U ? Iop_CmpGT32Ux4 : Iop_CmpGT32Sx4; break;
3608ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 3: return False;
3609ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  default: vassert(0);
3610ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               }
3611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else {
3612ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               switch (size) {
3613ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 0: op = U ? Iop_CmpGT8Ux8 : Iop_CmpGT8Sx8; break;
3614ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 1: op = U ? Iop_CmpGT16Ux4 : Iop_CmpGT16Sx4; break;
3615ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 2: op = U ? Iop_CmpGT32Ux2: Iop_CmpGT32Sx2; break;
3616ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 3: return False;
3617ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  default: vassert(0);
3618ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               }
3619ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
3620ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (B == 0) {
3621ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               /* VCGT  */
3622ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m)));
3623ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               DIP("vcgt.%c%u %c%u, %c%u, %c%u\n",
3624ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   U ? 'u' : 's', 8 << size,
3625ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', nreg, Q ? 'q' : 'd',
3626ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   mreg);
3627ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else {
3628ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               /* VCGE  */
3629ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               /* VCGE res, argn, argm
3630ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    is equal to
3631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  VCGT tmp, argm, argn
3632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  VNOT res, tmp */
3633ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               assign(res,
3634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      unop(Q ? Iop_NotV128 : Iop_Not64,
3635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           binop(op, mkexpr(arg_m), mkexpr(arg_n))));
3636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               DIP("vcge.%c%u %c%u, %c%u, %c%u\n",
3637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   U ? 'u' : 's', 8 << size,
3638ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', nreg, Q ? 'q' : 'd',
3639ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   mreg);
3640ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
3641ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
3642ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
3643ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 4:
3644ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (B == 0) {
3645ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* VSHL */
3646ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            IROp op, sub_op;
3647ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            IRTemp tmp;
3648ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (U) {
3649ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               switch (size) {
3650ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 0: op = Q ? Iop_Shl8x16 : Iop_Shl8x8; break;
3651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 1: op = Q ? Iop_Shl16x8 : Iop_Shl16x4; break;
3652ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 2: op = Q ? Iop_Shl32x4 : Iop_Shl32x2; break;
3653ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 3: op = Q ? Iop_Shl64x2 : Iop_Shl64; break;
3654ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  default: vassert(0);
3655ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               }
3656ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else {
3657ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               tmp = newTemp(Q ? Ity_V128 : Ity_I64);
3658ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               switch (size) {
3659ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 0:
3660ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op = Q ? Iop_Sar8x16 : Iop_Sar8x8;
3661ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     sub_op = Q ? Iop_Sub8x16 : Iop_Sub8x8;
3662ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     break;
3663ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 1:
3664ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op = Q ? Iop_Sar16x8 : Iop_Sar16x4;
3665ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     sub_op = Q ? Iop_Sub16x8 : Iop_Sub16x4;
3666ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     break;
3667ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 2:
3668ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op = Q ? Iop_Sar32x4 : Iop_Sar32x2;
3669ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     sub_op = Q ? Iop_Sub32x4 : Iop_Sub32x2;
3670ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     break;
3671ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 3:
3672ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op = Q ? Iop_Sar64x2 : Iop_Sar64;
3673ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     sub_op = Q ? Iop_Sub64x2 : Iop_Sub64;
3674ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     break;
3675ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  default:
3676ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     vassert(0);
3677ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               }
3678ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
3679ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (U) {
3680ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               if (!Q && (size == 3))
3681ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  assign(res, binop(op, mkexpr(arg_m),
3682ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                        unop(Iop_64to8, mkexpr(arg_n))));
3683ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               else
3684ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  assign(res, binop(op, mkexpr(arg_m), mkexpr(arg_n)));
3685ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else {
3686ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               if (Q)
3687ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  assign(tmp, binop(sub_op,
3688ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                    binop(Iop_64HLtoV128, mkU64(0), mkU64(0)),
3689ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                    mkexpr(arg_n)));
3690ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               else
3691ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  assign(tmp, binop(sub_op, mkU64(0), mkexpr(arg_n)));
3692ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               if (!Q && (size == 3))
3693ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  assign(res, binop(op, mkexpr(arg_m),
3694ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                        unop(Iop_64to8, mkexpr(tmp))));
3695ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               else
3696ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  assign(res, binop(op, mkexpr(arg_m), mkexpr(tmp)));
3697ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
3698ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            DIP("vshl.%c%u %c%u, %c%u, %c%u\n",
3699ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                U ? 'u' : 's', 8 << size,
3700ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg, Q ? 'q' : 'd',
3701ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                nreg);
3702ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
3703ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* VQSHL */
3704ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            IROp op, op_rev, op_shrn, op_shln, cmp_neq, cmp_gt;
3705ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            IRTemp tmp, shval, mask, old_shval;
3706ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            UInt i;
3707ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ULong esize;
3708ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            cmp_neq = Q ? Iop_CmpNEZ8x16 : Iop_CmpNEZ8x8;
3709ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            cmp_gt = Q ? Iop_CmpGT8Sx16 : Iop_CmpGT8Sx8;
3710ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (U) {
3711ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               switch (size) {
3712ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 0:
3713ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op = Q ? Iop_QShl8x16 : Iop_QShl8x8;
3714ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op_rev = Q ? Iop_Shr8x16 : Iop_Shr8x8;
3715ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op_shrn = Q ? Iop_ShrN8x16 : Iop_ShrN8x8;
3716ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op_shln = Q ? Iop_ShlN8x16 : Iop_ShlN8x8;
3717ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     break;
3718ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 1:
3719ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op = Q ? Iop_QShl16x8 : Iop_QShl16x4;
3720ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op_rev = Q ? Iop_Shr16x8 : Iop_Shr16x4;
3721ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op_shrn = Q ? Iop_ShrN16x8 : Iop_ShrN16x4;
3722ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op_shln = Q ? Iop_ShlN16x8 : Iop_ShlN16x4;
3723ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     break;
3724ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 2:
3725ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op = Q ? Iop_QShl32x4 : Iop_QShl32x2;
3726ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op_rev = Q ? Iop_Shr32x4 : Iop_Shr32x2;
3727ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op_shrn = Q ? Iop_ShrN32x4 : Iop_ShrN32x2;
3728ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op_shln = Q ? Iop_ShlN32x4 : Iop_ShlN32x2;
3729ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     break;
3730ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 3:
3731ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op = Q ? Iop_QShl64x2 : Iop_QShl64x1;
3732ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op_rev = Q ? Iop_Shr64x2 : Iop_Shr64;
3733ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op_shrn = Q ? Iop_ShrN64x2 : Iop_Shr64;
3734ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op_shln = Q ? Iop_ShlN64x2 : Iop_Shl64;
3735ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     break;
3736ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  default:
3737ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     vassert(0);
3738ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               }
3739ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else {
3740ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               switch (size) {
3741ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 0:
3742ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op = Q ? Iop_QSal8x16 : Iop_QSal8x8;
3743ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op_rev = Q ? Iop_Sar8x16 : Iop_Sar8x8;
3744ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op_shrn = Q ? Iop_ShrN8x16 : Iop_ShrN8x8;
3745ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op_shln = Q ? Iop_ShlN8x16 : Iop_ShlN8x8;
3746ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     break;
3747ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 1:
3748ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op = Q ? Iop_QSal16x8 : Iop_QSal16x4;
3749ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op_rev = Q ? Iop_Sar16x8 : Iop_Sar16x4;
3750ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op_shrn = Q ? Iop_ShrN16x8 : Iop_ShrN16x4;
3751ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op_shln = Q ? Iop_ShlN16x8 : Iop_ShlN16x4;
3752ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     break;
3753ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 2:
3754ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op = Q ? Iop_QSal32x4 : Iop_QSal32x2;
3755ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op_rev = Q ? Iop_Sar32x4 : Iop_Sar32x2;
3756ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op_shrn = Q ? Iop_ShrN32x4 : Iop_ShrN32x2;
3757ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op_shln = Q ? Iop_ShlN32x4 : Iop_ShlN32x2;
3758ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     break;
3759ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 3:
3760ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op = Q ? Iop_QSal64x2 : Iop_QSal64x1;
3761ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op_rev = Q ? Iop_Sar64x2 : Iop_Sar64;
3762ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op_shrn = Q ? Iop_ShrN64x2 : Iop_Shr64;
3763ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op_shln = Q ? Iop_ShlN64x2 : Iop_Shl64;
3764ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     break;
3765ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  default:
3766ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     vassert(0);
3767ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               }
3768ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
3769ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (Q) {
3770ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               tmp = newTemp(Ity_V128);
3771ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               shval = newTemp(Ity_V128);
3772ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               mask = newTemp(Ity_V128);
3773ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else {
3774ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               tmp = newTemp(Ity_I64);
3775ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               shval = newTemp(Ity_I64);
3776ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               mask = newTemp(Ity_I64);
3777ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
3778ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            assign(res, binop(op, mkexpr(arg_m), mkexpr(arg_n)));
3779ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#ifndef DISABLE_QC_FLAG
3780ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* Only least significant byte from second argument is used.
3781ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               Copy this byte to the whole vector element. */
3782ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            assign(shval, binop(op_shrn,
3783ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                binop(op_shln,
3784ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                       mkexpr(arg_n),
3785ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                       mkU8((8 << size) - 8)),
3786ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                mkU8((8 << size) - 8)));
3787ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            for(i = 0; i < size; i++) {
3788ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               old_shval = shval;
3789ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               shval = newTemp(Q ? Ity_V128 : Ity_I64);
3790ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               assign(shval, binop(Q ? Iop_OrV128 : Iop_Or64,
3791ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                   mkexpr(old_shval),
3792ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                   binop(op_shln,
3793ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                         mkexpr(old_shval),
3794ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                         mkU8(8 << i))));
3795ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
3796ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* If shift is greater or equal to the element size and
3797ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               element is non-zero, then QC flag should be set. */
3798ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            esize = (8 << size) - 1;
3799ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            esize = (esize <<  8) | esize;
3800ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            esize = (esize << 16) | esize;
3801ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            esize = (esize << 32) | esize;
3802ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            setFlag_QC(binop(Q ? Iop_AndV128 : Iop_And64,
3803ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             binop(cmp_gt, mkexpr(shval),
3804ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                           Q ? mkU128(esize) : mkU64(esize)),
3805ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             unop(cmp_neq, mkexpr(arg_m))),
3806ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       Q ? mkU128(0) : mkU64(0),
3807ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       Q, condT);
3808ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* Othervise QC flag should be set if shift value is positive and
3809ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               result beign rightshifted the same value is not equal to left
3810ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               argument. */
3811ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            assign(mask, binop(cmp_gt, mkexpr(shval),
3812ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                       Q ? mkU128(0) : mkU64(0)));
3813ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (!Q && size == 3)
3814ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               assign(tmp, binop(op_rev, mkexpr(res),
3815ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                         unop(Iop_64to8, mkexpr(arg_n))));
3816ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            else
3817ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               assign(tmp, binop(op_rev, mkexpr(res), mkexpr(arg_n)));
3818ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            setFlag_QC(binop(Q ? Iop_AndV128 : Iop_And64,
3819ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             mkexpr(tmp), mkexpr(mask)),
3820ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       binop(Q ? Iop_AndV128 : Iop_And64,
3821ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             mkexpr(arg_m), mkexpr(mask)),
3822ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       Q, condT);
3823ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
3824ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            DIP("vqshl.%c%u %c%u, %c%u, %c%u\n",
3825ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                U ? 'u' : 's', 8 << size,
3826ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg, Q ? 'q' : 'd',
3827ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                nreg);
3828ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
3829ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
3830ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 5:
3831ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (B == 0) {
3832ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* VRSHL */
3833b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            IROp op, op_shrn, op_shln, cmp_gt, op_add;
3834ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            IRTemp shval, old_shval, imm_val, round;
3835ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            UInt i;
3836ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ULong imm;
3837ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            cmp_gt = Q ? Iop_CmpGT8Sx16 : Iop_CmpGT8Sx8;
3838ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            imm = 1L;
3839ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            switch (size) {
3840ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               case 0: imm = (imm <<  8) | imm; /* fall through */
3841ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               case 1: imm = (imm << 16) | imm; /* fall through */
3842ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               case 2: imm = (imm << 32) | imm; /* fall through */
3843ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               case 3: break;
3844ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               default: vassert(0);
3845ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
3846ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            imm_val = newTemp(Q ? Ity_V128 : Ity_I64);
3847ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            round = newTemp(Q ? Ity_V128 : Ity_I64);
3848ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            assign(imm_val, Q ? mkU128(imm) : mkU64(imm));
3849ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (U) {
3850ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               switch (size) {
3851ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 0:
3852ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op = Q ? Iop_Shl8x16 : Iop_Shl8x8;
3853ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op_add = Q ? Iop_Add8x16 : Iop_Add8x8;
3854ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op_shrn = Q ? Iop_ShrN8x16 : Iop_ShrN8x8;
3855ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op_shln = Q ? Iop_ShlN8x16 : Iop_ShlN8x8;
3856ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     break;
3857ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 1:
3858ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op = Q ? Iop_Shl16x8 : Iop_Shl16x4;
3859ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op_add = Q ? Iop_Add16x8 : Iop_Add16x4;
3860ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op_shrn = Q ? Iop_ShrN16x8 : Iop_ShrN16x4;
3861ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op_shln = Q ? Iop_ShlN16x8 : Iop_ShlN16x4;
3862ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     break;
3863ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 2:
3864ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op = Q ? Iop_Shl32x4 : Iop_Shl32x2;
3865ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op_add = Q ? Iop_Add32x4 : Iop_Add32x2;
3866ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op_shrn = Q ? Iop_ShrN32x4 : Iop_ShrN32x2;
3867ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op_shln = Q ? Iop_ShlN32x4 : Iop_ShlN32x2;
3868ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     break;
3869ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 3:
3870ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op = Q ? Iop_Shl64x2 : Iop_Shl64;
3871ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op_add = Q ? Iop_Add64x2 : Iop_Add64;
3872ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op_shrn = Q ? Iop_ShrN64x2 : Iop_Shr64;
3873ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op_shln = Q ? Iop_ShlN64x2 : Iop_Shl64;
3874ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     break;
3875ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  default:
3876ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     vassert(0);
3877ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               }
3878ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else {
3879ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               switch (size) {
3880ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 0:
3881ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op = Q ? Iop_Sal8x16 : Iop_Sal8x8;
3882ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op_add = Q ? Iop_Add8x16 : Iop_Add8x8;
3883ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op_shrn = Q ? Iop_ShrN8x16 : Iop_ShrN8x8;
3884ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op_shln = Q ? Iop_ShlN8x16 : Iop_ShlN8x8;
3885ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     break;
3886ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 1:
3887ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op = Q ? Iop_Sal16x8 : Iop_Sal16x4;
3888ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op_add = Q ? Iop_Add16x8 : Iop_Add16x4;
3889ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op_shrn = Q ? Iop_ShrN16x8 : Iop_ShrN16x4;
3890ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op_shln = Q ? Iop_ShlN16x8 : Iop_ShlN16x4;
3891ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     break;
3892ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 2:
3893ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op = Q ? Iop_Sal32x4 : Iop_Sal32x2;
3894ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op_add = Q ? Iop_Add32x4 : Iop_Add32x2;
3895ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op_shrn = Q ? Iop_ShrN32x4 : Iop_ShrN32x2;
3896ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op_shln = Q ? Iop_ShlN32x4 : Iop_ShlN32x2;
3897ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     break;
3898ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 3:
3899ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op = Q ? Iop_Sal64x2 : Iop_Sal64x1;
3900ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op_add = Q ? Iop_Add64x2 : Iop_Add64;
3901ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op_shrn = Q ? Iop_ShrN64x2 : Iop_Shr64;
3902ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op_shln = Q ? Iop_ShlN64x2 : Iop_Shl64;
3903ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     break;
3904ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  default:
3905ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     vassert(0);
3906ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               }
3907ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
3908ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (Q) {
3909ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               shval = newTemp(Ity_V128);
3910ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else {
3911ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               shval = newTemp(Ity_I64);
3912ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
3913ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* Only least significant byte from second argument is used.
3914ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               Copy this byte to the whole vector element. */
3915ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            assign(shval, binop(op_shrn,
3916ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                binop(op_shln,
3917ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                       mkexpr(arg_n),
3918ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                       mkU8((8 << size) - 8)),
3919ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                mkU8((8 << size) - 8)));
3920ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            for (i = 0; i < size; i++) {
3921ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               old_shval = shval;
3922ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               shval = newTemp(Q ? Ity_V128 : Ity_I64);
3923ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               assign(shval, binop(Q ? Iop_OrV128 : Iop_Or64,
3924ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                   mkexpr(old_shval),
3925ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                   binop(op_shln,
3926ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                         mkexpr(old_shval),
3927ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                         mkU8(8 << i))));
3928ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
3929ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* Compute the result */
3930ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (!Q && size == 3 && U) {
3931ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               assign(round, binop(Q ? Iop_AndV128 : Iop_And64,
3932ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                   binop(op,
3933ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                         mkexpr(arg_m),
3934ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                         unop(Iop_64to8,
3935ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                              binop(op_add,
3936ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                                    mkexpr(arg_n),
3937ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                                    mkexpr(imm_val)))),
3938ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                   binop(Q ? Iop_AndV128 : Iop_And64,
3939ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                         mkexpr(imm_val),
3940ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                         binop(cmp_gt,
3941ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                               Q ? mkU128(0) : mkU64(0),
3942ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                               mkexpr(arg_n)))));
3943ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               assign(res, binop(op_add,
3944ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                 binop(op,
3945ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                       mkexpr(arg_m),
3946ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                       unop(Iop_64to8, mkexpr(arg_n))),
3947ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                 mkexpr(round)));
3948ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else {
3949ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               assign(round, binop(Q ? Iop_AndV128 : Iop_And64,
3950ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                   binop(op,
3951ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                         mkexpr(arg_m),
3952ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                         binop(op_add,
3953ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                               mkexpr(arg_n),
3954ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                               mkexpr(imm_val))),
3955ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                   binop(Q ? Iop_AndV128 : Iop_And64,
3956ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                         mkexpr(imm_val),
3957ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                         binop(cmp_gt,
3958ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                               Q ? mkU128(0) : mkU64(0),
3959ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                               mkexpr(arg_n)))));
3960ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               assign(res, binop(op_add,
3961ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                 binop(op, mkexpr(arg_m), mkexpr(arg_n)),
3962ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                 mkexpr(round)));
3963ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
3964ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            DIP("vrshl.%c%u %c%u, %c%u, %c%u\n",
3965ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                U ? 'u' : 's', 8 << size,
3966ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg, Q ? 'q' : 'd',
3967ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                nreg);
3968ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
3969ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* VQRSHL */
3970b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            IROp op, op_rev, op_shrn, op_shln, cmp_neq, cmp_gt, op_add;
3971ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            IRTemp tmp, shval, mask, old_shval, imm_val, round;
3972ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            UInt i;
3973ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ULong esize, imm;
3974ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            cmp_neq = Q ? Iop_CmpNEZ8x16 : Iop_CmpNEZ8x8;
3975ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            cmp_gt = Q ? Iop_CmpGT8Sx16 : Iop_CmpGT8Sx8;
3976ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            imm = 1L;
3977ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            switch (size) {
3978ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               case 0: imm = (imm <<  8) | imm; /* fall through */
3979ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               case 1: imm = (imm << 16) | imm; /* fall through */
3980ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               case 2: imm = (imm << 32) | imm; /* fall through */
3981ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               case 3: break;
3982ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               default: vassert(0);
3983ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
3984ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            imm_val = newTemp(Q ? Ity_V128 : Ity_I64);
3985ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            round = newTemp(Q ? Ity_V128 : Ity_I64);
3986ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            assign(imm_val, Q ? mkU128(imm) : mkU64(imm));
3987ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (U) {
3988ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               switch (size) {
3989ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 0:
3990ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op = Q ? Iop_QShl8x16 : Iop_QShl8x8;
3991ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op_add = Q ? Iop_Add8x16 : Iop_Add8x8;
3992ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op_rev = Q ? Iop_Shr8x16 : Iop_Shr8x8;
3993ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op_shrn = Q ? Iop_ShrN8x16 : Iop_ShrN8x8;
3994ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op_shln = Q ? Iop_ShlN8x16 : Iop_ShlN8x8;
3995ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     break;
3996ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 1:
3997ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op = Q ? Iop_QShl16x8 : Iop_QShl16x4;
3998ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op_add = Q ? Iop_Add16x8 : Iop_Add16x4;
3999ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op_rev = Q ? Iop_Shr16x8 : Iop_Shr16x4;
4000ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op_shrn = Q ? Iop_ShrN16x8 : Iop_ShrN16x4;
4001ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op_shln = Q ? Iop_ShlN16x8 : Iop_ShlN16x4;
4002ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     break;
4003ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 2:
4004ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op = Q ? Iop_QShl32x4 : Iop_QShl32x2;
4005ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op_add = Q ? Iop_Add32x4 : Iop_Add32x2;
4006ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op_rev = Q ? Iop_Shr32x4 : Iop_Shr32x2;
4007ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op_shrn = Q ? Iop_ShrN32x4 : Iop_ShrN32x2;
4008ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op_shln = Q ? Iop_ShlN32x4 : Iop_ShlN32x2;
4009ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     break;
4010ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 3:
4011ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op = Q ? Iop_QShl64x2 : Iop_QShl64x1;
4012ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op_add = Q ? Iop_Add64x2 : Iop_Add64;
4013ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op_rev = Q ? Iop_Shr64x2 : Iop_Shr64;
4014ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op_shrn = Q ? Iop_ShrN64x2 : Iop_Shr64;
4015ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op_shln = Q ? Iop_ShlN64x2 : Iop_Shl64;
4016ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     break;
4017ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  default:
4018ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     vassert(0);
4019ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               }
4020ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else {
4021ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               switch (size) {
4022ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 0:
4023ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op = Q ? Iop_QSal8x16 : Iop_QSal8x8;
4024ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op_add = Q ? Iop_Add8x16 : Iop_Add8x8;
4025ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op_rev = Q ? Iop_Sar8x16 : Iop_Sar8x8;
4026ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op_shrn = Q ? Iop_ShrN8x16 : Iop_ShrN8x8;
4027ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op_shln = Q ? Iop_ShlN8x16 : Iop_ShlN8x8;
4028ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     break;
4029ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 1:
4030ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op = Q ? Iop_QSal16x8 : Iop_QSal16x4;
4031ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op_add = Q ? Iop_Add16x8 : Iop_Add16x4;
4032ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op_rev = Q ? Iop_Sar16x8 : Iop_Sar16x4;
4033ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op_shrn = Q ? Iop_ShrN16x8 : Iop_ShrN16x4;
4034ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op_shln = Q ? Iop_ShlN16x8 : Iop_ShlN16x4;
4035ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     break;
4036ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 2:
4037ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op = Q ? Iop_QSal32x4 : Iop_QSal32x2;
4038ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op_add = Q ? Iop_Add32x4 : Iop_Add32x2;
4039ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op_rev = Q ? Iop_Sar32x4 : Iop_Sar32x2;
4040ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op_shrn = Q ? Iop_ShrN32x4 : Iop_ShrN32x2;
4041ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op_shln = Q ? Iop_ShlN32x4 : Iop_ShlN32x2;
4042ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     break;
4043ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 3:
4044ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op = Q ? Iop_QSal64x2 : Iop_QSal64x1;
4045ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op_add = Q ? Iop_Add64x2 : Iop_Add64;
4046ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op_rev = Q ? Iop_Sar64x2 : Iop_Sar64;
4047ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op_shrn = Q ? Iop_ShrN64x2 : Iop_Shr64;
4048ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op_shln = Q ? Iop_ShlN64x2 : Iop_Shl64;
4049ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     break;
4050ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  default:
4051ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     vassert(0);
4052ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               }
4053ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
4054ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (Q) {
4055ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               tmp = newTemp(Ity_V128);
4056ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               shval = newTemp(Ity_V128);
4057ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               mask = newTemp(Ity_V128);
4058ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else {
4059ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               tmp = newTemp(Ity_I64);
4060ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               shval = newTemp(Ity_I64);
4061ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               mask = newTemp(Ity_I64);
4062ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
4063ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* Only least significant byte from second argument is used.
4064ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               Copy this byte to the whole vector element. */
4065ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            assign(shval, binop(op_shrn,
4066ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                binop(op_shln,
4067ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                       mkexpr(arg_n),
4068ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                       mkU8((8 << size) - 8)),
4069ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                mkU8((8 << size) - 8)));
4070ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            for (i = 0; i < size; i++) {
4071ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               old_shval = shval;
4072ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               shval = newTemp(Q ? Ity_V128 : Ity_I64);
4073ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               assign(shval, binop(Q ? Iop_OrV128 : Iop_Or64,
4074ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                   mkexpr(old_shval),
4075ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                   binop(op_shln,
4076ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                         mkexpr(old_shval),
4077ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                         mkU8(8 << i))));
4078ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
4079ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* Compute the result */
4080ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            assign(round, binop(Q ? Iop_AndV128 : Iop_And64,
4081ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                binop(op,
4082ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                      mkexpr(arg_m),
4083ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                      binop(op_add,
4084ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                            mkexpr(arg_n),
4085ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                            mkexpr(imm_val))),
4086ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                binop(Q ? Iop_AndV128 : Iop_And64,
4087ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                      mkexpr(imm_val),
4088ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                      binop(cmp_gt,
4089ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                            Q ? mkU128(0) : mkU64(0),
4090ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                            mkexpr(arg_n)))));
4091ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            assign(res, binop(op_add,
4092ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              binop(op, mkexpr(arg_m), mkexpr(arg_n)),
4093ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              mkexpr(round)));
4094ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#ifndef DISABLE_QC_FLAG
4095ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* If shift is greater or equal to the element size and element is
4096ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               non-zero, then QC flag should be set. */
4097ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            esize = (8 << size) - 1;
4098ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            esize = (esize <<  8) | esize;
4099ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            esize = (esize << 16) | esize;
4100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            esize = (esize << 32) | esize;
4101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            setFlag_QC(binop(Q ? Iop_AndV128 : Iop_And64,
4102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             binop(cmp_gt, mkexpr(shval),
4103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                           Q ? mkU128(esize) : mkU64(esize)),
4104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             unop(cmp_neq, mkexpr(arg_m))),
4105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       Q ? mkU128(0) : mkU64(0),
4106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       Q, condT);
4107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* Othervise QC flag should be set if shift value is positive and
4108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               result beign rightshifted the same value is not equal to left
4109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               argument. */
4110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            assign(mask, binop(cmp_gt, mkexpr(shval),
4111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               Q ? mkU128(0) : mkU64(0)));
4112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (!Q && size == 3)
4113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               assign(tmp, binop(op_rev, mkexpr(res),
4114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                         unop(Iop_64to8, mkexpr(arg_n))));
4115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            else
4116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               assign(tmp, binop(op_rev, mkexpr(res), mkexpr(arg_n)));
4117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            setFlag_QC(binop(Q ? Iop_AndV128 : Iop_And64,
4118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             mkexpr(tmp), mkexpr(mask)),
4119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       binop(Q ? Iop_AndV128 : Iop_And64,
4120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             mkexpr(arg_m), mkexpr(mask)),
4121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       Q, condT);
4122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
4123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            DIP("vqrshl.%c%u %c%u, %c%u, %c%u\n",
4124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                U ? 'u' : 's', 8 << size,
4125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg, Q ? 'q' : 'd',
4126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                nreg);
4127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
4128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
4129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 6:
4130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* VMAX, VMIN  */
4131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (B == 0) {
4132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* VMAX */
4133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            IROp op;
4134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (U == 0) {
4135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               switch (size) {
4136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 0: op = Q ? Iop_Max8Sx16 : Iop_Max8Sx8; break;
4137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 1: op = Q ? Iop_Max16Sx8 : Iop_Max16Sx4; break;
4138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 2: op = Q ? Iop_Max32Sx4 : Iop_Max32Sx2; break;
4139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 3: return False;
4140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  default: vassert(0);
4141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               }
4142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else {
4143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               switch (size) {
4144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 0: op = Q ? Iop_Max8Ux16 : Iop_Max8Ux8; break;
4145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 1: op = Q ? Iop_Max16Ux8 : Iop_Max16Ux4; break;
4146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 2: op = Q ? Iop_Max32Ux4 : Iop_Max32Ux2; break;
4147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 3: return False;
4148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  default: vassert(0);
4149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               }
4150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
4151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m)));
4152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            DIP("vmax.%c%u %c%u, %c%u, %c%u\n",
4153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                U ? 'u' : 's', 8 << size,
4154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', nreg, Q ? 'q' : 'd',
4155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                mreg);
4156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
4157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* VMIN */
4158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            IROp op;
4159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (U == 0) {
4160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               switch (size) {
4161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 0: op = Q ? Iop_Min8Sx16 : Iop_Min8Sx8; break;
4162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 1: op = Q ? Iop_Min16Sx8 : Iop_Min16Sx4; break;
4163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 2: op = Q ? Iop_Min32Sx4 : Iop_Min32Sx2; break;
4164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 3: return False;
4165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  default: vassert(0);
4166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               }
4167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else {
4168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               switch (size) {
4169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 0: op = Q ? Iop_Min8Ux16 : Iop_Min8Ux8; break;
4170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 1: op = Q ? Iop_Min16Ux8 : Iop_Min16Ux4; break;
4171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 2: op = Q ? Iop_Min32Ux4 : Iop_Min32Ux2; break;
4172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 3: return False;
4173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  default: vassert(0);
4174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               }
4175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
4176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m)));
4177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            DIP("vmin.%c%u %c%u, %c%u, %c%u\n",
4178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                U ? 'u' : 's', 8 << size,
4179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', nreg, Q ? 'q' : 'd',
4180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                mreg);
4181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
4182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
4183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 7:
4184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (B == 0) {
4185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* VABD */
4186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            IROp op_cmp, op_sub;
4187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            IRTemp cond;
4188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if ((theInstr >> 23) & 1) {
4189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               vpanic("VABDL should not be in dis_neon_data_3same\n");
4190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
4191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (Q) {
4192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               switch (size) {
4193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 0:
4194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op_cmp = U ? Iop_CmpGT8Ux16 : Iop_CmpGT8Sx16;
4195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op_sub = Iop_Sub8x16;
4196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     break;
4197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 1:
4198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op_cmp = U ? Iop_CmpGT16Ux8 : Iop_CmpGT16Sx8;
4199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op_sub = Iop_Sub16x8;
4200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     break;
4201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 2:
4202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op_cmp = U ? Iop_CmpGT32Ux4 : Iop_CmpGT32Sx4;
4203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op_sub = Iop_Sub32x4;
4204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     break;
4205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 3:
4206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     return False;
4207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  default:
4208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     vassert(0);
4209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               }
4210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else {
4211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               switch (size) {
4212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 0:
4213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op_cmp = U ? Iop_CmpGT8Ux8 : Iop_CmpGT8Sx8;
4214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op_sub = Iop_Sub8x8;
4215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     break;
4216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 1:
4217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op_cmp = U ? Iop_CmpGT16Ux4 : Iop_CmpGT16Sx4;
4218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op_sub = Iop_Sub16x4;
4219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     break;
4220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 2:
4221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op_cmp = U ? Iop_CmpGT32Ux2 : Iop_CmpGT32Sx2;
4222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op_sub = Iop_Sub32x2;
4223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     break;
4224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 3:
4225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     return False;
4226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  default:
4227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     vassert(0);
4228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               }
4229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
4230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (Q) {
4231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               cond = newTemp(Ity_V128);
4232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else {
4233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               cond = newTemp(Ity_I64);
4234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
4235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            assign(cond, binop(op_cmp, mkexpr(arg_n), mkexpr(arg_m)));
4236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            assign(res, binop(Q ? Iop_OrV128 : Iop_Or64,
4237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              binop(Q ? Iop_AndV128 : Iop_And64,
4238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                    binop(op_sub, mkexpr(arg_n),
4239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                                  mkexpr(arg_m)),
4240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                    mkexpr(cond)),
4241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              binop(Q ? Iop_AndV128 : Iop_And64,
4242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                    binop(op_sub, mkexpr(arg_m),
4243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                                  mkexpr(arg_n)),
4244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                    unop(Q ? Iop_NotV128 : Iop_Not64,
4245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                         mkexpr(cond)))));
4246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            DIP("vabd.%c%u %c%u, %c%u, %c%u\n",
4247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                U ? 'u' : 's', 8 << size,
4248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', nreg, Q ? 'q' : 'd',
4249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                mreg);
4250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
4251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* VABA */
4252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            IROp op_cmp, op_sub, op_add;
4253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            IRTemp cond, acc, tmp;
4254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if ((theInstr >> 23) & 1) {
4255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               vpanic("VABAL should not be in dis_neon_data_3same");
4256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
4257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (Q) {
4258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               switch (size) {
4259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 0:
4260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op_cmp = U ? Iop_CmpGT8Ux16 : Iop_CmpGT8Sx16;
4261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op_sub = Iop_Sub8x16;
4262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op_add = Iop_Add8x16;
4263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     break;
4264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 1:
4265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op_cmp = U ? Iop_CmpGT16Ux8 : Iop_CmpGT16Sx8;
4266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op_sub = Iop_Sub16x8;
4267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op_add = Iop_Add16x8;
4268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     break;
4269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 2:
4270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op_cmp = U ? Iop_CmpGT32Ux4 : Iop_CmpGT32Sx4;
4271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op_sub = Iop_Sub32x4;
4272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op_add = Iop_Add32x4;
4273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     break;
4274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 3:
4275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     return False;
4276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  default:
4277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     vassert(0);
4278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               }
4279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else {
4280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               switch (size) {
4281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 0:
4282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op_cmp = U ? Iop_CmpGT8Ux8 : Iop_CmpGT8Sx8;
4283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op_sub = Iop_Sub8x8;
4284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op_add = Iop_Add8x8;
4285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     break;
4286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 1:
4287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op_cmp = U ? Iop_CmpGT16Ux4 : Iop_CmpGT16Sx4;
4288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op_sub = Iop_Sub16x4;
4289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op_add = Iop_Add16x4;
4290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     break;
4291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 2:
4292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op_cmp = U ? Iop_CmpGT32Ux2 : Iop_CmpGT32Sx2;
4293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op_sub = Iop_Sub32x2;
4294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op_add = Iop_Add32x2;
4295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     break;
4296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 3:
4297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     return False;
4298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  default:
4299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     vassert(0);
4300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               }
4301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
4302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (Q) {
4303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               cond = newTemp(Ity_V128);
4304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               acc = newTemp(Ity_V128);
4305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               tmp = newTemp(Ity_V128);
4306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               assign(acc, getQReg(dreg));
4307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else {
4308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               cond = newTemp(Ity_I64);
4309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               acc = newTemp(Ity_I64);
4310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               tmp = newTemp(Ity_I64);
4311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               assign(acc, getDRegI64(dreg));
4312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
4313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            assign(cond, binop(op_cmp, mkexpr(arg_n), mkexpr(arg_m)));
4314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            assign(tmp, binop(Q ? Iop_OrV128 : Iop_Or64,
4315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              binop(Q ? Iop_AndV128 : Iop_And64,
4316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                    binop(op_sub, mkexpr(arg_n),
4317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                                  mkexpr(arg_m)),
4318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                    mkexpr(cond)),
4319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              binop(Q ? Iop_AndV128 : Iop_And64,
4320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                    binop(op_sub, mkexpr(arg_m),
4321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                                  mkexpr(arg_n)),
4322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                    unop(Q ? Iop_NotV128 : Iop_Not64,
4323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                         mkexpr(cond)))));
4324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            assign(res, binop(op_add, mkexpr(acc), mkexpr(tmp)));
4325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            DIP("vaba.%c%u %c%u, %c%u, %c%u\n",
4326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                U ? 'u' : 's', 8 << size,
4327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', nreg, Q ? 'q' : 'd',
4328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                mreg);
4329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
4330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
4331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 8:
4332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (B == 0) {
4333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            IROp op;
4334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (U == 0) {
4335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               /* VADD  */
4336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               switch (size) {
4337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 0: op = Q ? Iop_Add8x16 : Iop_Add8x8; break;
4338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 1: op = Q ? Iop_Add16x8 : Iop_Add16x4; break;
4339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 2: op = Q ? Iop_Add32x4 : Iop_Add32x2; break;
4340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 3: op = Q ? Iop_Add64x2 : Iop_Add64; break;
4341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  default: vassert(0);
4342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               }
4343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               DIP("vadd.i%u %c%u, %c%u, %c%u\n",
4344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   8 << size, Q ? 'q' : 'd',
4345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   dreg, Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg);
4346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else {
4347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               /* VSUB  */
4348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               switch (size) {
4349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 0: op = Q ? Iop_Sub8x16 : Iop_Sub8x8; break;
4350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 1: op = Q ? Iop_Sub16x8 : Iop_Sub16x4; break;
4351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 2: op = Q ? Iop_Sub32x4 : Iop_Sub32x2; break;
4352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 3: op = Q ? Iop_Sub64x2 : Iop_Sub64; break;
4353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  default: vassert(0);
4354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               }
4355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               DIP("vsub.i%u %c%u, %c%u, %c%u\n",
4356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   8 << size, Q ? 'q' : 'd',
4357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   dreg, Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg);
4358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
4359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m)));
4360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
4361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            IROp op;
4362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            switch (size) {
4363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               case 0: op = Q ? Iop_CmpNEZ8x16 : Iop_CmpNEZ8x8; break;
4364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               case 1: op = Q ? Iop_CmpNEZ16x8 : Iop_CmpNEZ16x4; break;
4365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               case 2: op = Q ? Iop_CmpNEZ32x4 : Iop_CmpNEZ32x2; break;
4366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               case 3: op = Q ? Iop_CmpNEZ64x2 : Iop_CmpwNEZ64; break;
4367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               default: vassert(0);
4368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
4369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (U == 0) {
4370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               /* VTST  */
4371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               assign(res, unop(op, binop(Q ? Iop_AndV128 : Iop_And64,
4372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                          mkexpr(arg_n),
4373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                          mkexpr(arg_m))));
4374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               DIP("vtst.%u %c%u, %c%u, %c%u\n",
4375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   8 << size, Q ? 'q' : 'd',
4376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   dreg, Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg);
4377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else {
4378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               /* VCEQ  */
4379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               assign(res, unop(Q ? Iop_NotV128 : Iop_Not64,
4380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                unop(op,
4381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                     binop(Q ? Iop_XorV128 : Iop_Xor64,
4382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                           mkexpr(arg_n),
4383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                           mkexpr(arg_m)))));
4384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               DIP("vceq.i%u %c%u, %c%u, %c%u\n",
4385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   8 << size, Q ? 'q' : 'd',
4386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   dreg, Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg);
4387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
4388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
4389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
4390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 9:
4391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (B == 0) {
4392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* VMLA, VMLS (integer) */
4393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            IROp op, op2;
4394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            UInt P = (theInstr >> 24) & 1;
4395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (P) {
4396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               switch (size) {
4397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 0:
4398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op = Q ? Iop_Mul8x16 : Iop_Mul8x8;
4399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op2 = Q ? Iop_Sub8x16 : Iop_Sub8x8;
4400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     break;
4401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 1:
4402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op = Q ? Iop_Mul16x8 : Iop_Mul16x4;
4403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op2 = Q ? Iop_Sub16x8 : Iop_Sub16x4;
4404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     break;
4405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 2:
4406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op = Q ? Iop_Mul32x4 : Iop_Mul32x2;
4407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op2 = Q ? Iop_Sub32x4 : Iop_Sub32x2;
4408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     break;
4409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 3:
4410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     return False;
4411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  default:
4412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     vassert(0);
4413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               }
4414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else {
4415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               switch (size) {
4416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 0:
4417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op = Q ? Iop_Mul8x16 : Iop_Mul8x8;
4418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op2 = Q ? Iop_Add8x16 : Iop_Add8x8;
4419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     break;
4420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 1:
4421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op = Q ? Iop_Mul16x8 : Iop_Mul16x4;
4422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op2 = Q ? Iop_Add16x8 : Iop_Add16x4;
4423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     break;
4424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 2:
4425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op = Q ? Iop_Mul32x4 : Iop_Mul32x2;
4426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op2 = Q ? Iop_Add32x4 : Iop_Add32x2;
4427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     break;
4428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 3:
4429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     return False;
4430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  default:
4431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     vassert(0);
4432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               }
4433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
4434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            assign(res, binop(op2,
4435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              Q ? getQReg(dreg) : getDRegI64(dreg),
4436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              binop(op, mkexpr(arg_n), mkexpr(arg_m))));
4437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            DIP("vml%c.i%u %c%u, %c%u, %c%u\n",
4438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                P ? 's' : 'a', 8 << size,
4439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', nreg, Q ? 'q' : 'd',
4440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                mreg);
4441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
4442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* VMUL */
4443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            IROp op;
4444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            UInt P = (theInstr >> 24) & 1;
4445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (P) {
4446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               switch (size) {
4447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 0:
4448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op = Q ? Iop_PolynomialMul8x16 : Iop_PolynomialMul8x8;
4449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     break;
4450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 1: case 2: case 3: return False;
4451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  default: vassert(0);
4452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               }
4453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else {
4454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               switch (size) {
4455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 0: op = Q ? Iop_Mul8x16 : Iop_Mul8x8; break;
4456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 1: op = Q ? Iop_Mul16x8 : Iop_Mul16x4; break;
4457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 2: op = Q ? Iop_Mul32x4 : Iop_Mul32x2; break;
4458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 3: return False;
4459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  default: vassert(0);
4460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               }
4461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
4462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m)));
4463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            DIP("vmul.%c%u %c%u, %c%u, %c%u\n",
4464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                P ? 'p' : 'i', 8 << size,
4465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', nreg, Q ? 'q' : 'd',
4466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                mreg);
4467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
4468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
4469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 10: {
4470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* VPMAX, VPMIN  */
4471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         UInt P = (theInstr >> 4) & 1;
4472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IROp op;
4473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (Q)
4474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return False;
4475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (P) {
4476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            switch (size) {
4477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               case 0: op = U ? Iop_PwMin8Ux8  : Iop_PwMin8Sx8; break;
4478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               case 1: op = U ? Iop_PwMin16Ux4 : Iop_PwMin16Sx4; break;
4479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               case 2: op = U ? Iop_PwMin32Ux2 : Iop_PwMin32Sx2; break;
4480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               case 3: return False;
4481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               default: vassert(0);
4482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
4483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
4484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            switch (size) {
4485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               case 0: op = U ? Iop_PwMax8Ux8  : Iop_PwMax8Sx8; break;
4486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               case 1: op = U ? Iop_PwMax16Ux4 : Iop_PwMax16Sx4; break;
4487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               case 2: op = U ? Iop_PwMax32Ux2 : Iop_PwMax32Sx2; break;
4488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               case 3: return False;
4489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               default: vassert(0);
4490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
4491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
4492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m)));
4493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("vp%s.%c%u %c%u, %c%u, %c%u\n",
4494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             P ? "min" : "max", U ? 'u' : 's',
4495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             8 << size, Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', nreg,
4496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             Q ? 'q' : 'd', mreg);
4497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
4498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
4499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 11:
4500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (B == 0) {
4501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (U == 0) {
4502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               /* VQDMULH  */
4503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               IROp op ,op2;
4504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               ULong imm;
4505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               switch (size) {
4506ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 0: case 3:
4507ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     return False;
4508ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 1:
4509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op = Q ? Iop_QDMulHi16Sx8 : Iop_QDMulHi16Sx4;
4510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op2 = Q ? Iop_CmpEQ16x8 : Iop_CmpEQ16x4;
4511ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     imm = 1LL << 15;
4512ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     imm = (imm << 16) | imm;
4513ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     imm = (imm << 32) | imm;
4514ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     break;
4515ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 2:
4516ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op = Q ? Iop_QDMulHi32Sx4 : Iop_QDMulHi32Sx2;
4517ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op2 = Q ? Iop_CmpEQ32x4 : Iop_CmpEQ32x2;
4518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     imm = 1LL << 31;
4519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     imm = (imm << 32) | imm;
4520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     break;
4521ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  default:
4522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     vassert(0);
4523ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               }
4524ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m)));
4525ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#ifndef DISABLE_QC_FLAG
4526ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               setFlag_QC(binop(Q ? Iop_AndV128 : Iop_And64,
4527ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                binop(op2, mkexpr(arg_n),
4528ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                           Q ? mkU128(imm) : mkU64(imm)),
4529ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                binop(op2, mkexpr(arg_m),
4530ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                           Q ? mkU128(imm) : mkU64(imm))),
4531ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          Q ? mkU128(0) : mkU64(0),
4532ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          Q, condT);
4533ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
4534ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               DIP("vqdmulh.s%u %c%u, %c%u, %c%u\n",
4535ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   8 << size, Q ? 'q' : 'd',
4536ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   dreg, Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg);
4537ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else {
4538ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               /* VQRDMULH */
4539ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               IROp op ,op2;
4540ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               ULong imm;
4541ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               switch(size) {
4542ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 0: case 3:
4543ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     return False;
4544ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 1:
4545ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     imm = 1LL << 15;
4546ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     imm = (imm << 16) | imm;
4547ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     imm = (imm << 32) | imm;
4548ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op = Q ? Iop_QRDMulHi16Sx8 : Iop_QRDMulHi16Sx4;
4549ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op2 = Q ? Iop_CmpEQ16x8 : Iop_CmpEQ16x4;
4550ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     break;
4551ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 2:
4552ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     imm = 1LL << 31;
4553ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     imm = (imm << 32) | imm;
4554ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op = Q ? Iop_QRDMulHi32Sx4 : Iop_QRDMulHi32Sx2;
4555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op2 = Q ? Iop_CmpEQ32x4 : Iop_CmpEQ32x2;
4556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     break;
4557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  default:
4558ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     vassert(0);
4559ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               }
4560ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m)));
4561ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#ifndef DISABLE_QC_FLAG
4562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               setFlag_QC(binop(Q ? Iop_AndV128 : Iop_And64,
4563ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                binop(op2, mkexpr(arg_n),
4564ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                           Q ? mkU128(imm) : mkU64(imm)),
4565ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                binop(op2, mkexpr(arg_m),
4566ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                           Q ? mkU128(imm) : mkU64(imm))),
4567ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          Q ? mkU128(0) : mkU64(0),
4568ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          Q, condT);
4569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
4570ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               DIP("vqrdmulh.s%u %c%u, %c%u, %c%u\n",
4571ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   8 << size, Q ? 'q' : 'd',
4572ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   dreg, Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg);
4573ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
4574ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
4575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (U == 0) {
4576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               /* VPADD */
4577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               IROp op;
4578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               if (Q)
4579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  return False;
4580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               switch (size) {
4581ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 0: op = Q ? Iop_PwAdd8x16 : Iop_PwAdd8x8;  break;
4582ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 1: op = Q ? Iop_PwAdd16x8 : Iop_PwAdd16x4; break;
4583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 2: op = Q ? Iop_PwAdd32x4 : Iop_PwAdd32x2; break;
4584ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 3: return False;
4585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  default: vassert(0);
4586ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               }
4587ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m)));
4588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               DIP("vpadd.i%d %c%u, %c%u, %c%u\n",
4589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   8 << size, Q ? 'q' : 'd',
4590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   dreg, Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg);
4591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
4592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
4593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
4594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Starting from here these are FP SIMD cases */
4595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 13:
4596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (B == 0) {
4597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            IROp op;
4598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (U == 0) {
4599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               if ((C >> 1) == 0) {
4600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  /* VADD  */
4601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  op = Q ? Iop_Add32Fx4 : Iop_Add32Fx2 ;
4602ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  DIP("vadd.f32 %c%u, %c%u, %c%u\n",
4603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      Q ? 'q' : 'd', dreg,
4604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg);
4605ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               } else {
4606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  /* VSUB  */
4607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  op = Q ? Iop_Sub32Fx4 : Iop_Sub32Fx2 ;
4608ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  DIP("vsub.f32 %c%u, %c%u, %c%u\n",
4609ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      Q ? 'q' : 'd', dreg,
4610ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg);
4611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               }
4612ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else {
4613ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               if ((C >> 1) == 0) {
4614ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  /* VPADD */
4615ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  if (Q)
4616ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     return False;
4617ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  op = Iop_PwAdd32Fx2;
4618ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  DIP("vpadd.f32 d%u, d%u, d%u\n", dreg, nreg, mreg);
4619ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               } else {
4620ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  /* VABD  */
4621ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  if (Q) {
4622ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     assign(res, unop(Iop_Abs32Fx4,
4623ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                      binop(Iop_Sub32Fx4,
4624ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                            mkexpr(arg_n),
4625ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                            mkexpr(arg_m))));
4626ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  } else {
4627ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     assign(res, unop(Iop_Abs32Fx2,
4628ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                      binop(Iop_Sub32Fx2,
4629ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                            mkexpr(arg_n),
4630ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                            mkexpr(arg_m))));
4631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  }
4632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  DIP("vabd.f32 %c%u, %c%u, %c%u\n",
4633ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      Q ? 'q' : 'd', dreg,
4634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg);
4635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  break;
4636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               }
4637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
4638ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m)));
4639ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
4640ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (U == 0) {
4641ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               /* VMLA, VMLS  */
4642ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               IROp op, op2;
4643ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               UInt P = (theInstr >> 21) & 1;
4644ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               if (P) {
4645ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  switch (size & 1) {
4646ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     case 0:
4647ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        op = Q ? Iop_Mul32Fx4 : Iop_Mul32Fx2;
4648ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        op2 = Q ? Iop_Sub32Fx4 : Iop_Sub32Fx2;
4649ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        break;
4650ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     case 1: return False;
4651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     default: vassert(0);
4652ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  }
4653ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               } else {
4654ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  switch (size & 1) {
4655ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     case 0:
4656ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        op = Q ? Iop_Mul32Fx4 : Iop_Mul32Fx2;
4657ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        op2 = Q ? Iop_Add32Fx4 : Iop_Add32Fx2;
4658ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        break;
4659ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     case 1: return False;
4660ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     default: vassert(0);
4661ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  }
4662ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               }
4663ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               assign(res, binop(op2,
4664ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                 Q ? getQReg(dreg) : getDRegI64(dreg),
4665ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                 binop(op, mkexpr(arg_n), mkexpr(arg_m))));
4666ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4667ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               DIP("vml%c.f32 %c%u, %c%u, %c%u\n",
4668ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   P ? 's' : 'a', Q ? 'q' : 'd',
4669ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   dreg, Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg);
4670ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else {
4671ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               /* VMUL  */
4672ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               IROp op;
4673ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               if ((C >> 1) != 0)
4674ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  return False;
4675ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               op = Q ? Iop_Mul32Fx4 : Iop_Mul32Fx2 ;
4676ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m)));
4677ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               DIP("vmul.f32 %c%u, %c%u, %c%u\n",
4678ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   Q ? 'q' : 'd', dreg,
4679ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg);
4680ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
4681ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
4682ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
4683ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 14:
4684ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (B == 0) {
4685ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (U == 0) {
4686ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               if ((C >> 1) == 0) {
4687ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  /* VCEQ  */
4688ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  IROp op;
4689ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  if ((theInstr >> 20) & 1)
4690ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     return False;
4691ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  op = Q ? Iop_CmpEQ32Fx4 : Iop_CmpEQ32Fx2;
4692ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m)));
4693ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  DIP("vceq.f32 %c%u, %c%u, %c%u\n",
4694ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      Q ? 'q' : 'd', dreg,
4695ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg);
4696ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               } else {
4697ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  return False;
4698ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               }
4699ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else {
4700ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               if ((C >> 1) == 0) {
4701ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  /* VCGE  */
4702ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  IROp op;
4703ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  if ((theInstr >> 20) & 1)
4704ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     return False;
4705ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  op = Q ? Iop_CmpGE32Fx4 : Iop_CmpGE32Fx2;
4706ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m)));
4707ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  DIP("vcge.f32 %c%u, %c%u, %c%u\n",
4708ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      Q ? 'q' : 'd', dreg,
4709ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg);
4710ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               } else {
4711ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  /* VCGT  */
4712ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  IROp op;
4713ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  if ((theInstr >> 20) & 1)
4714ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     return False;
4715ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  op = Q ? Iop_CmpGT32Fx4 : Iop_CmpGT32Fx2;
4716ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m)));
4717ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  DIP("vcgt.f32 %c%u, %c%u, %c%u\n",
4718ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      Q ? 'q' : 'd', dreg,
4719ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg);
4720ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               }
4721ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
4722ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
4723ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (U == 1) {
4724ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               /* VACGE, VACGT */
4725ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               UInt op_bit = (theInstr >> 21) & 1;
4726ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               IROp op, op2;
4727ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               op2 = Q ? Iop_Abs32Fx4 : Iop_Abs32Fx2;
4728ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               if (op_bit) {
4729ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  op = Q ? Iop_CmpGT32Fx4 : Iop_CmpGT32Fx2;
4730ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  assign(res, binop(op,
4731ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                    unop(op2, mkexpr(arg_n)),
4732ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                    unop(op2, mkexpr(arg_m))));
4733ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               } else {
4734ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  op = Q ? Iop_CmpGE32Fx4 : Iop_CmpGE32Fx2;
4735ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  assign(res, binop(op,
4736ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                    unop(op2, mkexpr(arg_n)),
4737ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                    unop(op2, mkexpr(arg_m))));
4738ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               }
4739ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               DIP("vacg%c.f32 %c%u, %c%u, %c%u\n", op_bit ? 't' : 'e',
4740ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', nreg,
4741ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   Q ? 'q' : 'd', mreg);
4742ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
4743ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
4744ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
4745ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 15:
4746ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (B == 0) {
4747ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (U == 0) {
4748ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               /* VMAX, VMIN  */
4749ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               IROp op;
4750ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               if ((theInstr >> 20) & 1)
4751ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  return False;
4752ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               if ((theInstr >> 21) & 1) {
4753ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  op = Q ? Iop_Min32Fx4 : Iop_Min32Fx2;
4754ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  DIP("vmin.f32 %c%u, %c%u, %c%u\n", Q ? 'q' : 'd', dreg,
4755ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg);
4756ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               } else {
4757ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  op = Q ? Iop_Max32Fx4 : Iop_Max32Fx2;
4758ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  DIP("vmax.f32 %c%u, %c%u, %c%u\n", Q ? 'q' : 'd', dreg,
4759ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg);
4760ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               }
4761ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m)));
4762ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else {
4763ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               /* VPMAX, VPMIN   */
4764ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               IROp op;
4765ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               if (Q)
4766ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  return False;
4767ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               if ((theInstr >> 20) & 1)
4768ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  return False;
4769ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               if ((theInstr >> 21) & 1) {
4770ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  op = Iop_PwMin32Fx2;
4771ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  DIP("vpmin.f32 d%u, d%u, d%u\n", dreg, nreg, mreg);
4772ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               } else {
4773ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  op = Iop_PwMax32Fx2;
4774ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  DIP("vpmax.f32 d%u, d%u, d%u\n", dreg, nreg, mreg);
4775ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               }
4776ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m)));
4777ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
4778ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
4779ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (U == 0) {
4780ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               if ((C >> 1) == 0) {
4781ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  /* VRECPS */
4782ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  if ((theInstr >> 20) & 1)
4783ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     return False;
4784ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  assign(res, binop(Q ? Iop_Recps32Fx4 : Iop_Recps32Fx2,
4785ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                    mkexpr(arg_n),
4786ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                    mkexpr(arg_m)));
4787ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  DIP("vrecps.f32 %c%u, %c%u, %c%u\n", Q ? 'q' : 'd', dreg,
4788ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg);
4789ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               } else {
4790ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  /* VRSQRTS  */
4791ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  if ((theInstr >> 20) & 1)
4792ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     return False;
4793ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  assign(res, binop(Q ? Iop_Rsqrts32Fx4 : Iop_Rsqrts32Fx2,
4794ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                    mkexpr(arg_n),
4795ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                    mkexpr(arg_m)));
4796ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  DIP("vrsqrts.f32 %c%u, %c%u, %c%u\n", Q ? 'q' : 'd', dreg,
4797ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg);
4798ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               }
4799ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
4800ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
4801ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
4802ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
4803ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4804ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (Q) {
4805ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putQReg(dreg, mkexpr(res), condT);
4806ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
4807ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putDRegI64(dreg, mkexpr(res), condT);
4808ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
4809ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4810ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return True;
4811ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4812ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4813ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* A7.4.2 Three registers of different length */
4814ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
4815ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownBool dis_neon_data_3diff ( UInt theInstr, IRTemp condT )
4816ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
4817ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt A = (theInstr >> 8) & 0xf;
4818ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt B = (theInstr >> 20) & 3;
4819ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt U = (theInstr >> 24) & 1;
4820ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt P = (theInstr >> 9) & 1;
4821ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt mreg = get_neon_m_regno(theInstr);
4822ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt nreg = get_neon_n_regno(theInstr);
4823ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt dreg = get_neon_d_regno(theInstr);
4824ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt size = B;
4825ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ULong imm;
4826ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp res, arg_m, arg_n, cond, tmp;
4827ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IROp cvt, cvt2, cmp, op, op2, sh, add;
4828ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (A) {
4829ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0: case 1: case 2: case 3:
4830ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* VADDL, VADDW, VSUBL, VSUBW */
4831ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (dreg & 1)
4832ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return False;
4833ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         dreg >>= 1;
4834ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         size = B;
4835ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         switch (size) {
4836ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 0:
4837b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               cvt = U ? Iop_Widen8Uto16x8 : Iop_Widen8Sto16x8;
4838ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               op = (A & 2) ? Iop_Sub16x8 : Iop_Add16x8;
4839ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
4840ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 1:
4841b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               cvt = U ? Iop_Widen16Uto32x4 : Iop_Widen16Sto32x4;
4842ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               op = (A & 2) ? Iop_Sub32x4 : Iop_Add32x4;
4843ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
4844ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 2:
4845b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               cvt = U ? Iop_Widen32Uto64x2 : Iop_Widen32Sto64x2;
4846ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               op = (A & 2) ? Iop_Sub64x2 : Iop_Add64x2;
4847ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
4848ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 3:
4849ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               return False;
4850ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            default:
4851ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               vassert(0);
4852ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
4853ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         arg_n = newTemp(Ity_V128);
4854ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         arg_m = newTemp(Ity_V128);
4855ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (A & 1) {
4856ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (nreg & 1)
4857ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               return False;
4858ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            nreg >>= 1;
4859ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            assign(arg_n, getQReg(nreg));
4860ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
4861ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            assign(arg_n, unop(cvt, getDRegI64(nreg)));
4862ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
4863ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign(arg_m, unop(cvt, getDRegI64(mreg)));
4864ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putQReg(dreg, binop(op, mkexpr(arg_n), mkexpr(arg_m)),
4865ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       condT);
4866ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("v%s%c.%c%u q%u, %c%u, d%u\n", (A & 2) ? "sub" : "add",
4867ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             (A & 1) ? 'w' : 'l', U ? 'u' : 's', 8 << size, dreg,
4868ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             (A & 1) ? 'q' : 'd', nreg, mreg);
4869ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return True;
4870ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 4:
4871ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* VADDHN, VRADDHN */
4872ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (mreg & 1)
4873ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return False;
4874ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         mreg >>= 1;
4875ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (nreg & 1)
4876ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return False;
4877ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         nreg >>= 1;
4878ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         size = B;
4879ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         switch (size) {
4880ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 0:
4881ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               op = Iop_Add16x8;
4882b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               cvt = Iop_NarrowUn16to8x8;
4883ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               sh = Iop_ShrN16x8;
4884ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               imm = 1U << 7;
4885ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               imm = (imm << 16) | imm;
4886ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               imm = (imm << 32) | imm;
4887ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
4888ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 1:
4889ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               op = Iop_Add32x4;
4890b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               cvt = Iop_NarrowUn32to16x4;
4891ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               sh = Iop_ShrN32x4;
4892ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               imm = 1U << 15;
4893ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               imm = (imm << 32) | imm;
4894ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
4895ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 2:
4896ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               op = Iop_Add64x2;
4897b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               cvt = Iop_NarrowUn64to32x2;
4898ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               sh = Iop_ShrN64x2;
4899ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               imm = 1U << 31;
4900ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
4901ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 3:
4902ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               return False;
4903ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            default:
4904ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               vassert(0);
4905ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
4906ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         tmp = newTemp(Ity_V128);
4907ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         res = newTemp(Ity_V128);
4908ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign(tmp, binop(op, getQReg(nreg), getQReg(mreg)));
4909ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (U) {
4910ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* VRADDHN */
4911ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            assign(res, binop(op, mkexpr(tmp),
4912ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     binop(Iop_64HLtoV128, mkU64(imm), mkU64(imm))));
4913ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
4914ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            assign(res, mkexpr(tmp));
4915ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
4916ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putDRegI64(dreg, unop(cvt, binop(sh, mkexpr(res), mkU8(8 << size))),
4917ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    condT);
4918ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("v%saddhn.i%u d%u, q%u, q%u\n", U ? "r" : "", 16 << size, dreg,
4919ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             nreg, mreg);
4920ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return True;
4921ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 5:
4922ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* VABAL */
4923ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (!((theInstr >> 23) & 1)) {
4924ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vpanic("VABA should not be in dis_neon_data_3diff\n");
4925ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
4926ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (dreg & 1)
4927ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return False;
4928ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         dreg >>= 1;
4929ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         switch (size) {
4930ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 0:
4931ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               cmp = U ? Iop_CmpGT8Ux8 : Iop_CmpGT8Sx8;
4932b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               cvt = U ? Iop_Widen8Uto16x8 : Iop_Widen8Sto16x8;
4933b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               cvt2 = Iop_Widen8Sto16x8;
4934ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               op = Iop_Sub16x8;
4935ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               op2 = Iop_Add16x8;
4936ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
4937ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 1:
4938ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               cmp = U ? Iop_CmpGT16Ux4 : Iop_CmpGT16Sx4;
4939b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               cvt = U ? Iop_Widen16Uto32x4 : Iop_Widen16Sto32x4;
4940b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               cvt2 = Iop_Widen16Sto32x4;
4941ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               op = Iop_Sub32x4;
4942ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               op2 = Iop_Add32x4;
4943ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
4944ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 2:
4945ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               cmp = U ? Iop_CmpGT32Ux2 : Iop_CmpGT32Sx2;
4946b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               cvt = U ? Iop_Widen32Uto64x2 : Iop_Widen32Sto64x2;
4947b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               cvt2 = Iop_Widen32Sto64x2;
4948ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               op = Iop_Sub64x2;
4949ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               op2 = Iop_Add64x2;
4950ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
4951ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 3:
4952ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               return False;
4953ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            default:
4954ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               vassert(0);
4955ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
4956ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         arg_n = newTemp(Ity_V128);
4957ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         arg_m = newTemp(Ity_V128);
4958ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         cond = newTemp(Ity_V128);
4959ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         res = newTemp(Ity_V128);
4960ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign(arg_n, unop(cvt, getDRegI64(nreg)));
4961ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign(arg_m, unop(cvt, getDRegI64(mreg)));
4962ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign(cond, unop(cvt2, binop(cmp, getDRegI64(nreg),
4963ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                            getDRegI64(mreg))));
4964ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign(res, binop(op2,
4965ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           binop(Iop_OrV128,
4966ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                 binop(Iop_AndV128,
4967ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                       binop(op, mkexpr(arg_n), mkexpr(arg_m)),
4968ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                       mkexpr(cond)),
4969ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                 binop(Iop_AndV128,
4970ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                       binop(op, mkexpr(arg_m), mkexpr(arg_n)),
4971ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                       unop(Iop_NotV128, mkexpr(cond)))),
4972ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           getQReg(dreg)));
4973ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putQReg(dreg, mkexpr(res), condT);
4974ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("vabal.%c%u q%u, d%u, d%u\n", U ? 'u' : 's', 8 << size, dreg,
4975ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             nreg, mreg);
4976ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return True;
4977ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 6:
4978ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* VSUBHN, VRSUBHN */
4979ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (mreg & 1)
4980ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return False;
4981ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         mreg >>= 1;
4982ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (nreg & 1)
4983ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return False;
4984ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         nreg >>= 1;
4985ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         size = B;
4986ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         switch (size) {
4987ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 0:
4988ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               op = Iop_Sub16x8;
4989ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               op2 = Iop_Add16x8;
4990b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               cvt = Iop_NarrowUn16to8x8;
4991ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               sh = Iop_ShrN16x8;
4992ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               imm = 1U << 7;
4993ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               imm = (imm << 16) | imm;
4994ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               imm = (imm << 32) | imm;
4995ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
4996ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 1:
4997ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               op = Iop_Sub32x4;
4998ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               op2 = Iop_Add32x4;
4999b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               cvt = Iop_NarrowUn32to16x4;
5000ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               sh = Iop_ShrN32x4;
5001ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               imm = 1U << 15;
5002ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               imm = (imm << 32) | imm;
5003ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
5004ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 2:
5005ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               op = Iop_Sub64x2;
5006ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               op2 = Iop_Add64x2;
5007b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               cvt = Iop_NarrowUn64to32x2;
5008ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               sh = Iop_ShrN64x2;
5009ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               imm = 1U << 31;
5010ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
5011ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 3:
5012ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               return False;
5013ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            default:
5014ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               vassert(0);
5015ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
5016ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         tmp = newTemp(Ity_V128);
5017ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         res = newTemp(Ity_V128);
5018ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign(tmp, binop(op, getQReg(nreg), getQReg(mreg)));
5019ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (U) {
5020ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* VRSUBHN */
5021ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            assign(res, binop(op2, mkexpr(tmp),
5022ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     binop(Iop_64HLtoV128, mkU64(imm), mkU64(imm))));
5023ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
5024ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            assign(res, mkexpr(tmp));
5025ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
5026ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putDRegI64(dreg, unop(cvt, binop(sh, mkexpr(res), mkU8(8 << size))),
5027ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    condT);
5028ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("v%ssubhn.i%u d%u, q%u, q%u\n", U ? "r" : "", 16 << size, dreg,
5029ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             nreg, mreg);
5030ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return True;
5031ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 7:
5032ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* VABDL */
5033ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (!((theInstr >> 23) & 1)) {
5034ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vpanic("VABL should not be in dis_neon_data_3diff\n");
5035ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
5036ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (dreg & 1)
5037ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return False;
5038ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         dreg >>= 1;
5039ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         switch (size) {
5040ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 0:
5041ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               cmp = U ? Iop_CmpGT8Ux8 : Iop_CmpGT8Sx8;
5042b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               cvt = U ? Iop_Widen8Uto16x8 : Iop_Widen8Sto16x8;
5043b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               cvt2 = Iop_Widen8Sto16x8;
5044ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               op = Iop_Sub16x8;
5045ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
5046ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 1:
5047ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               cmp = U ? Iop_CmpGT16Ux4 : Iop_CmpGT16Sx4;
5048b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               cvt = U ? Iop_Widen16Uto32x4 : Iop_Widen16Sto32x4;
5049b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               cvt2 = Iop_Widen16Sto32x4;
5050ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               op = Iop_Sub32x4;
5051ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
5052ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 2:
5053ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               cmp = U ? Iop_CmpGT32Ux2 : Iop_CmpGT32Sx2;
5054b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               cvt = U ? Iop_Widen32Uto64x2 : Iop_Widen32Sto64x2;
5055b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               cvt2 = Iop_Widen32Sto64x2;
5056ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               op = Iop_Sub64x2;
5057ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
5058ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 3:
5059ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               return False;
5060ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            default:
5061ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               vassert(0);
5062ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
5063ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         arg_n = newTemp(Ity_V128);
5064ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         arg_m = newTemp(Ity_V128);
5065ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         cond = newTemp(Ity_V128);
5066ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         res = newTemp(Ity_V128);
5067ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign(arg_n, unop(cvt, getDRegI64(nreg)));
5068ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign(arg_m, unop(cvt, getDRegI64(mreg)));
5069ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign(cond, unop(cvt2, binop(cmp, getDRegI64(nreg),
5070ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                            getDRegI64(mreg))));
5071ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign(res, binop(Iop_OrV128,
5072ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           binop(Iop_AndV128,
5073ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                 binop(op, mkexpr(arg_n), mkexpr(arg_m)),
5074ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                 mkexpr(cond)),
5075ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           binop(Iop_AndV128,
5076ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                 binop(op, mkexpr(arg_m), mkexpr(arg_n)),
5077ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                 unop(Iop_NotV128, mkexpr(cond)))));
5078ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putQReg(dreg, mkexpr(res), condT);
5079ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("vabdl.%c%u q%u, d%u, d%u\n", U ? 'u' : 's', 8 << size, dreg,
5080ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             nreg, mreg);
5081ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return True;
5082ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 8:
5083ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 10:
5084ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* VMLAL, VMLSL (integer) */
5085ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (dreg & 1)
5086ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return False;
5087ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         dreg >>= 1;
5088ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         size = B;
5089ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         switch (size) {
5090ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 0:
5091ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               op = U ? Iop_Mull8Ux8 : Iop_Mull8Sx8;
5092ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               op2 = P ? Iop_Sub16x8 : Iop_Add16x8;
5093ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
5094ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 1:
5095ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               op = U ? Iop_Mull16Ux4 : Iop_Mull16Sx4;
5096ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               op2 = P ? Iop_Sub32x4 : Iop_Add32x4;
5097ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
5098ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 2:
5099ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               op = U ? Iop_Mull32Ux2 : Iop_Mull32Sx2;
5100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               op2 = P ? Iop_Sub64x2 : Iop_Add64x2;
5101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
5102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 3:
5103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               return False;
5104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            default:
5105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               vassert(0);
5106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
5107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         res = newTemp(Ity_V128);
5108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign(res, binop(op, getDRegI64(nreg),getDRegI64(mreg)));
5109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putQReg(dreg, binop(op2, getQReg(dreg), mkexpr(res)), condT);
5110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("vml%cl.%c%u q%u, d%u, d%u\n", P ? 's' : 'a', U ? 'u' : 's',
5111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             8 << size, dreg, nreg, mreg);
5112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return True;
5113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 9:
5114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 11:
5115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* VQDMLAL, VQDMLSL */
5116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (U)
5117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return False;
5118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (dreg & 1)
5119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return False;
5120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         dreg >>= 1;
5121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         size = B;
5122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         switch (size) {
5123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 0: case 3:
5124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               return False;
5125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 1:
5126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               op = Iop_QDMulLong16Sx4;
5127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               cmp = Iop_CmpEQ16x4;
5128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               add = P ? Iop_QSub32Sx4 : Iop_QAdd32Sx4;
5129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               op2 = P ? Iop_Sub32x4 : Iop_Add32x4;
5130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               imm = 1LL << 15;
5131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               imm = (imm << 16) | imm;
5132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               imm = (imm << 32) | imm;
5133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
5134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 2:
5135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               op = Iop_QDMulLong32Sx2;
5136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               cmp = Iop_CmpEQ32x2;
5137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               add = P ? Iop_QSub64Sx2 : Iop_QAdd64Sx2;
5138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               op2 = P ? Iop_Sub64x2 : Iop_Add64x2;
5139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               imm = 1LL << 31;
5140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               imm = (imm << 32) | imm;
5141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
5142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            default:
5143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               vassert(0);
5144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
5145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         res = newTemp(Ity_V128);
5146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         tmp = newTemp(Ity_V128);
5147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign(res, binop(op, getDRegI64(nreg), getDRegI64(mreg)));
5148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#ifndef DISABLE_QC_FLAG
5149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign(tmp, binop(op2, getQReg(dreg), mkexpr(res)));
5150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         setFlag_QC(mkexpr(tmp), binop(add, getQReg(dreg), mkexpr(res)),
5151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    True, condT);
5152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         setFlag_QC(binop(Iop_And64,
5153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          binop(cmp, getDRegI64(nreg), mkU64(imm)),
5154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          binop(cmp, getDRegI64(mreg), mkU64(imm))),
5155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    mkU64(0),
5156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    False, condT);
5157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
5158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putQReg(dreg, binop(add, getQReg(dreg), mkexpr(res)), condT);
5159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("vqdml%cl.s%u q%u, d%u, d%u\n", P ? 's' : 'a', 8 << size, dreg,
5160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             nreg, mreg);
5161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return True;
5162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 12:
5163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 14:
5164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* VMULL (integer or polynomial) */
5165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (dreg & 1)
5166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return False;
5167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         dreg >>= 1;
5168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         size = B;
5169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         switch (size) {
5170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 0:
5171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               op = (U) ? Iop_Mull8Ux8 : Iop_Mull8Sx8;
5172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               if (P)
5173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  op = Iop_PolynomialMull8x8;
5174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
5175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 1:
5176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               op = (U) ? Iop_Mull16Ux4 : Iop_Mull16Sx4;
5177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
5178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 2:
5179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               op = (U) ? Iop_Mull32Ux2 : Iop_Mull32Sx2;
5180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
5181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            default:
5182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               vassert(0);
5183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
5184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putQReg(dreg, binop(op, getDRegI64(nreg),
5185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                 getDRegI64(mreg)), condT);
5186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("vmull.%c%u q%u, d%u, d%u\n", P ? 'p' : (U ? 'u' : 's'),
5187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               8 << size, dreg, nreg, mreg);
5188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return True;
5189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 13:
5190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* VQDMULL */
5191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (U)
5192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return False;
5193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (dreg & 1)
5194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return False;
5195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         dreg >>= 1;
5196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         size = B;
5197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         switch (size) {
5198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 0:
5199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 3:
5200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               return False;
5201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 1:
5202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               op = Iop_QDMulLong16Sx4;
5203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               op2 = Iop_CmpEQ16x4;
5204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               imm = 1LL << 15;
5205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               imm = (imm << 16) | imm;
5206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               imm = (imm << 32) | imm;
5207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
5208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 2:
5209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               op = Iop_QDMulLong32Sx2;
5210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               op2 = Iop_CmpEQ32x2;
5211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               imm = 1LL << 31;
5212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               imm = (imm << 32) | imm;
5213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
5214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            default:
5215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               vassert(0);
5216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
5217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putQReg(dreg, binop(op, getDRegI64(nreg), getDRegI64(mreg)),
5218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               condT);
5219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#ifndef DISABLE_QC_FLAG
5220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         setFlag_QC(binop(Iop_And64,
5221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          binop(op2, getDRegI64(nreg), mkU64(imm)),
5222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          binop(op2, getDRegI64(mreg), mkU64(imm))),
5223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    mkU64(0),
5224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    False, condT);
5225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
5226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("vqdmull.s%u q%u, d%u, d%u\n", 8 << size, dreg, nreg, mreg);
5227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return True;
5228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
5229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return False;
5230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
5231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return False;
5232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
5233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* A7.4.3 Two registers and a scalar */
5235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
5236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownBool dis_neon_data_2reg_and_scalar ( UInt theInstr, IRTemp condT )
5237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
5238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  define INSN(_bMax,_bMin)  SLICE_UInt(theInstr, (_bMax), (_bMin))
5239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt U = INSN(24,24);
5240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt dreg = get_neon_d_regno(theInstr & ~(1 << 6));
5241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt nreg = get_neon_n_regno(theInstr & ~(1 << 6));
5242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt mreg = get_neon_m_regno(theInstr & ~(1 << 6));
5243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt size = INSN(21,20);
5244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt index;
5245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt Q = INSN(24,24);
5246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (INSN(27,25) != 1 || INSN(23,23) != 1
5248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       || INSN(6,6) != 1 || INSN(4,4) != 0)
5249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return False;
5250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* VMLA, VMLS (scalar)  */
5252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if ((INSN(11,8) & BITS4(1,0,1,0)) == BITS4(0,0,0,0)) {
5253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp res, arg_m, arg_n;
5254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IROp dup, get, op, op2, add, sub;
5255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (Q) {
5256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if ((dreg & 1) || (nreg & 1))
5257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return False;
5258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         dreg >>= 1;
5259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         nreg >>= 1;
5260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         res = newTemp(Ity_V128);
5261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         arg_m = newTemp(Ity_V128);
5262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         arg_n = newTemp(Ity_V128);
5263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign(arg_n, getQReg(nreg));
5264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         switch(size) {
5265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 1:
5266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               dup = Iop_Dup16x8;
5267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               get = Iop_GetElem16x4;
5268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               index = mreg >> 3;
5269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               mreg &= 7;
5270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
5271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 2:
5272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               dup = Iop_Dup32x4;
5273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               get = Iop_GetElem32x2;
5274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               index = mreg >> 4;
5275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               mreg &= 0xf;
5276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
5277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 0:
5278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 3:
5279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               return False;
5280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            default:
5281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               vassert(0);
5282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
5283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign(arg_m, unop(dup, binop(get, getDRegI64(mreg), mkU8(index))));
5284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else {
5285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         res = newTemp(Ity_I64);
5286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         arg_m = newTemp(Ity_I64);
5287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         arg_n = newTemp(Ity_I64);
5288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign(arg_n, getDRegI64(nreg));
5289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         switch(size) {
5290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 1:
5291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               dup = Iop_Dup16x4;
5292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               get = Iop_GetElem16x4;
5293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               index = mreg >> 3;
5294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               mreg &= 7;
5295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
5296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 2:
5297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               dup = Iop_Dup32x2;
5298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               get = Iop_GetElem32x2;
5299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               index = mreg >> 4;
5300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               mreg &= 0xf;
5301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
5302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 0:
5303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 3:
5304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               return False;
5305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            default:
5306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               vassert(0);
5307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
5308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign(arg_m, unop(dup, binop(get, getDRegI64(mreg), mkU8(index))));
5309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
5310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (INSN(8,8)) {
5311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         switch (size) {
5312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 2:
5313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               op = Q ? Iop_Mul32Fx4 : Iop_Mul32Fx2;
5314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               add = Q ? Iop_Add32Fx4 : Iop_Add32Fx2;
5315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               sub = Q ? Iop_Sub32Fx4 : Iop_Sub32Fx2;
5316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
5317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 0:
5318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 1:
5319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 3:
5320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               return False;
5321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            default:
5322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               vassert(0);
5323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
5324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else {
5325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         switch (size) {
5326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 1:
5327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               op = Q ? Iop_Mul16x8 : Iop_Mul16x4;
5328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               add = Q ? Iop_Add16x8 : Iop_Add16x4;
5329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               sub = Q ? Iop_Sub16x8 : Iop_Sub16x4;
5330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
5331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 2:
5332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               op = Q ? Iop_Mul32x4 : Iop_Mul32x2;
5333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               add = Q ? Iop_Add32x4 : Iop_Add32x2;
5334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               sub = Q ? Iop_Sub32x4 : Iop_Sub32x2;
5335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
5336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 0:
5337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 3:
5338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               return False;
5339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            default:
5340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               vassert(0);
5341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
5342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
5343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      op2 = INSN(10,10) ? sub : add;
5344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m)));
5345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (Q)
5346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putQReg(dreg, binop(op2, getQReg(dreg), mkexpr(res)),
5347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               condT);
5348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      else
5349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putDRegI64(dreg, binop(op2, getDRegI64(dreg), mkexpr(res)),
5350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    condT);
5351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("vml%c.%c%u %c%u, %c%u, d%u[%u]\n", INSN(10,10) ? 's' : 'a',
5352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            INSN(8,8) ? 'f' : 'i', 8 << size,
5353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', nreg, mreg, index);
5354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return True;
5355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
5356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* VMLAL, VMLSL (scalar)   */
5358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if ((INSN(11,8) & BITS4(1,0,1,1)) == BITS4(0,0,1,0)) {
5359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp res, arg_m, arg_n;
5360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IROp dup, get, op, op2, add, sub;
5361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (dreg & 1)
5362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return False;
5363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      dreg >>= 1;
5364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      res = newTemp(Ity_V128);
5365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      arg_m = newTemp(Ity_I64);
5366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      arg_n = newTemp(Ity_I64);
5367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign(arg_n, getDRegI64(nreg));
5368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch(size) {
5369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case 1:
5370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            dup = Iop_Dup16x4;
5371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            get = Iop_GetElem16x4;
5372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            index = mreg >> 3;
5373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            mreg &= 7;
5374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
5375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case 2:
5376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            dup = Iop_Dup32x2;
5377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            get = Iop_GetElem32x2;
5378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            index = mreg >> 4;
5379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            mreg &= 0xf;
5380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
5381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case 0:
5382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case 3:
5383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return False;
5384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         default:
5385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vassert(0);
5386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
5387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign(arg_m, unop(dup, binop(get, getDRegI64(mreg), mkU8(index))));
5388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch (size) {
5389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case 1:
5390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            op = U ? Iop_Mull16Ux4 : Iop_Mull16Sx4;
5391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            add = Iop_Add32x4;
5392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            sub = Iop_Sub32x4;
5393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
5394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case 2:
5395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            op = U ? Iop_Mull32Ux2 : Iop_Mull32Sx2;
5396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            add = Iop_Add64x2;
5397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            sub = Iop_Sub64x2;
5398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
5399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case 0:
5400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case 3:
5401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return False;
5402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         default:
5403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vassert(0);
5404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
5405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      op2 = INSN(10,10) ? sub : add;
5406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m)));
5407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putQReg(dreg, binop(op2, getQReg(dreg), mkexpr(res)), condT);
5408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("vml%cl.%c%u q%u, d%u, d%u[%u]\n",
5409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          INSN(10,10) ? 's' : 'a', U ? 'u' : 's',
5410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          8 << size, dreg, nreg, mreg, index);
5411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return True;
5412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
5413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* VQDMLAL, VQDMLSL (scalar)  */
5415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if ((INSN(11,8) & BITS4(1,0,1,1)) == BITS4(0,0,1,1) && !U) {
5416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp res, arg_m, arg_n, tmp;
5417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IROp dup, get, op, op2, add, cmp;
5418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt P = INSN(10,10);
5419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ULong imm;
5420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (dreg & 1)
5421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return False;
5422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      dreg >>= 1;
5423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      res = newTemp(Ity_V128);
5424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      arg_m = newTemp(Ity_I64);
5425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      arg_n = newTemp(Ity_I64);
5426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign(arg_n, getDRegI64(nreg));
5427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch(size) {
5428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case 1:
5429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            dup = Iop_Dup16x4;
5430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            get = Iop_GetElem16x4;
5431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            index = mreg >> 3;
5432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            mreg &= 7;
5433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
5434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case 2:
5435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            dup = Iop_Dup32x2;
5436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            get = Iop_GetElem32x2;
5437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            index = mreg >> 4;
5438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            mreg &= 0xf;
5439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
5440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case 0:
5441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case 3:
5442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return False;
5443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         default:
5444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vassert(0);
5445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
5446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign(arg_m, unop(dup, binop(get, getDRegI64(mreg), mkU8(index))));
5447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch (size) {
5448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case 0:
5449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case 3:
5450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return False;
5451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case 1:
5452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            op = Iop_QDMulLong16Sx4;
5453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            cmp = Iop_CmpEQ16x4;
5454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            add = P ? Iop_QSub32Sx4 : Iop_QAdd32Sx4;
5455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            op2 = P ? Iop_Sub32x4 : Iop_Add32x4;
5456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            imm = 1LL << 15;
5457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            imm = (imm << 16) | imm;
5458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            imm = (imm << 32) | imm;
5459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
5460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case 2:
5461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            op = Iop_QDMulLong32Sx2;
5462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            cmp = Iop_CmpEQ32x2;
5463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            add = P ? Iop_QSub64Sx2 : Iop_QAdd64Sx2;
5464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            op2 = P ? Iop_Sub64x2 : Iop_Add64x2;
5465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            imm = 1LL << 31;
5466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            imm = (imm << 32) | imm;
5467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
5468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         default:
5469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vassert(0);
5470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
5471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      res = newTemp(Ity_V128);
5472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      tmp = newTemp(Ity_V128);
5473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m)));
5474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#ifndef DISABLE_QC_FLAG
5475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign(tmp, binop(op2, getQReg(dreg), mkexpr(res)));
5476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      setFlag_QC(binop(Iop_And64,
5477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       binop(cmp, mkexpr(arg_n), mkU64(imm)),
5478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       binop(cmp, mkexpr(arg_m), mkU64(imm))),
5479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 mkU64(0),
5480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 False, condT);
5481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      setFlag_QC(mkexpr(tmp), binop(add, getQReg(dreg), mkexpr(res)),
5482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 True, condT);
5483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
5484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putQReg(dreg, binop(add, getQReg(dreg), mkexpr(res)), condT);
5485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("vqdml%cl.s%u q%u, d%u, d%u[%u]\n", P ? 's' : 'a', 8 << size,
5486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          dreg, nreg, mreg, index);
5487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return True;
5488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
5489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* VMUL (by scalar)  */
5491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if ((INSN(11,8) & BITS4(1,1,1,0)) == BITS4(1,0,0,0)) {
5492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp res, arg_m, arg_n;
5493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IROp dup, get, op;
5494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (Q) {
5495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if ((dreg & 1) || (nreg & 1))
5496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return False;
5497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         dreg >>= 1;
5498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         nreg >>= 1;
5499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         res = newTemp(Ity_V128);
5500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         arg_m = newTemp(Ity_V128);
5501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         arg_n = newTemp(Ity_V128);
5502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign(arg_n, getQReg(nreg));
5503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         switch(size) {
5504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 1:
5505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               dup = Iop_Dup16x8;
5506ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               get = Iop_GetElem16x4;
5507ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               index = mreg >> 3;
5508ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               mreg &= 7;
5509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
5510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 2:
5511ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               dup = Iop_Dup32x4;
5512ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               get = Iop_GetElem32x2;
5513ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               index = mreg >> 4;
5514ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               mreg &= 0xf;
5515ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
5516ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 0:
5517ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 3:
5518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               return False;
5519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            default:
5520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               vassert(0);
5521ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
5522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign(arg_m, unop(dup, binop(get, getDRegI64(mreg), mkU8(index))));
5523ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else {
5524ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         res = newTemp(Ity_I64);
5525ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         arg_m = newTemp(Ity_I64);
5526ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         arg_n = newTemp(Ity_I64);
5527ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign(arg_n, getDRegI64(nreg));
5528ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         switch(size) {
5529ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 1:
5530ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               dup = Iop_Dup16x4;
5531ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               get = Iop_GetElem16x4;
5532ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               index = mreg >> 3;
5533ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               mreg &= 7;
5534ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
5535ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 2:
5536ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               dup = Iop_Dup32x2;
5537ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               get = Iop_GetElem32x2;
5538ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               index = mreg >> 4;
5539ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               mreg &= 0xf;
5540ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
5541ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 0:
5542ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 3:
5543ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               return False;
5544ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            default:
5545ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               vassert(0);
5546ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
5547ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign(arg_m, unop(dup, binop(get, getDRegI64(mreg), mkU8(index))));
5548ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
5549b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      if (INSN(8,8)) {
5550b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         switch (size) {
5551b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            case 2:
5552b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               op = Q ? Iop_Mul32Fx4 : Iop_Mul32Fx2;
5553b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               break;
5554b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            case 0:
5555b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            case 1:
5556b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            case 3:
5557b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               return False;
5558b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            default:
5559b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               vassert(0);
5560b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         }
5561b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      } else {
5562b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         switch (size) {
5563b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            case 1:
5564b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               op = Q ? Iop_Mul16x8 : Iop_Mul16x4;
5565b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               break;
5566b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            case 2:
5567b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               op = Q ? Iop_Mul32x4 : Iop_Mul32x2;
5568b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               break;
5569b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            case 0:
5570b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            case 3:
5571b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               return False;
5572b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            default:
5573b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               vassert(0);
5574b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         }
5575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
5576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m)));
5577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (Q)
5578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putQReg(dreg, mkexpr(res), condT);
5579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      else
5580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putDRegI64(dreg, mkexpr(res), condT);
5581b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      DIP("vmul.%c%u %c%u, %c%u, d%u[%u]\n", INSN(8,8) ? 'f' : 'i',
5582b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov          8 << size, Q ? 'q' : 'd', dreg,
5583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          Q ? 'q' : 'd', nreg, mreg, index);
5584ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return True;
5585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
5586ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5587ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* VMULL (scalar) */
5588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (INSN(11,8) == BITS4(1,0,1,0)) {
5589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp res, arg_m, arg_n;
5590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IROp dup, get, op;
5591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (dreg & 1)
5592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return False;
5593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      dreg >>= 1;
5594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      res = newTemp(Ity_V128);
5595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      arg_m = newTemp(Ity_I64);
5596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      arg_n = newTemp(Ity_I64);
5597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign(arg_n, getDRegI64(nreg));
5598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch(size) {
5599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case 1:
5600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            dup = Iop_Dup16x4;
5601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            get = Iop_GetElem16x4;
5602ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            index = mreg >> 3;
5603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            mreg &= 7;
5604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
5605ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case 2:
5606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            dup = Iop_Dup32x2;
5607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            get = Iop_GetElem32x2;
5608ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            index = mreg >> 4;
5609ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            mreg &= 0xf;
5610ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
5611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case 0:
5612ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case 3:
5613ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return False;
5614ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         default:
5615ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vassert(0);
5616ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
5617ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign(arg_m, unop(dup, binop(get, getDRegI64(mreg), mkU8(index))));
5618ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch (size) {
5619ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case 1: op = U ? Iop_Mull16Ux4 : Iop_Mull16Sx4; break;
5620ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case 2: op = U ? Iop_Mull32Ux2 : Iop_Mull32Sx2; break;
5621ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case 0: case 3: return False;
5622ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         default: vassert(0);
5623ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
5624ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m)));
5625ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putQReg(dreg, mkexpr(res), condT);
5626ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("vmull.%c%u q%u, d%u, d%u[%u]\n", U ? 'u' : 's', 8 << size, dreg,
5627ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          nreg, mreg, index);
5628ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return True;
5629ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
5630ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* VQDMULL */
5632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (INSN(11,8) == BITS4(1,0,1,1) && !U) {
5633ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IROp op ,op2, dup, get;
5634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ULong imm;
5635b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      IRTemp arg_m, arg_n;
5636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (dreg & 1)
5637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return False;
5638ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      dreg >>= 1;
5639ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      arg_m = newTemp(Ity_I64);
5640ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      arg_n = newTemp(Ity_I64);
5641ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign(arg_n, getDRegI64(nreg));
5642ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch(size) {
5643ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case 1:
5644ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            dup = Iop_Dup16x4;
5645ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            get = Iop_GetElem16x4;
5646ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            index = mreg >> 3;
5647ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            mreg &= 7;
5648ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
5649ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case 2:
5650ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            dup = Iop_Dup32x2;
5651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            get = Iop_GetElem32x2;
5652ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            index = mreg >> 4;
5653ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            mreg &= 0xf;
5654ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
5655ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case 0:
5656ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case 3:
5657ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return False;
5658ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         default:
5659ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vassert(0);
5660ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
5661ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign(arg_m, unop(dup, binop(get, getDRegI64(mreg), mkU8(index))));
5662ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch (size) {
5663ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case 0:
5664ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case 3:
5665ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return False;
5666ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case 1:
5667ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            op = Iop_QDMulLong16Sx4;
5668ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            op2 = Iop_CmpEQ16x4;
5669ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            imm = 1LL << 15;
5670ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            imm = (imm << 16) | imm;
5671ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            imm = (imm << 32) | imm;
5672ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
5673ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case 2:
5674ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            op = Iop_QDMulLong32Sx2;
5675ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            op2 = Iop_CmpEQ32x2;
5676ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            imm = 1LL << 31;
5677ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            imm = (imm << 32) | imm;
5678ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
5679ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         default:
5680ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vassert(0);
5681ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
5682ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putQReg(dreg, binop(op, mkexpr(arg_n), mkexpr(arg_m)),
5683ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            condT);
5684ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#ifndef DISABLE_QC_FLAG
5685ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      setFlag_QC(binop(Iop_And64,
5686ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       binop(op2, mkexpr(arg_n), mkU64(imm)),
5687ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       binop(op2, mkexpr(arg_m), mkU64(imm))),
5688ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 mkU64(0),
5689ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 False, condT);
5690ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
5691ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("vqdmull.s%u q%u, d%u, d%u[%u]\n", 8 << size, dreg, nreg, mreg,
5692ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          index);
5693ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return True;
5694ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
5695ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5696ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* VQDMULH */
5697ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (INSN(11,8) == BITS4(1,1,0,0)) {
5698ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IROp op ,op2, dup, get;
5699ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ULong imm;
5700ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp res, arg_m, arg_n;
5701ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (Q) {
5702ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if ((dreg & 1) || (nreg & 1))
5703ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return False;
5704ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         dreg >>= 1;
5705ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         nreg >>= 1;
5706ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         res = newTemp(Ity_V128);
5707ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         arg_m = newTemp(Ity_V128);
5708ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         arg_n = newTemp(Ity_V128);
5709ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign(arg_n, getQReg(nreg));
5710ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         switch(size) {
5711ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 1:
5712ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               dup = Iop_Dup16x8;
5713ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               get = Iop_GetElem16x4;
5714ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               index = mreg >> 3;
5715ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               mreg &= 7;
5716ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
5717ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 2:
5718ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               dup = Iop_Dup32x4;
5719ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               get = Iop_GetElem32x2;
5720ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               index = mreg >> 4;
5721ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               mreg &= 0xf;
5722ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
5723ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 0:
5724ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 3:
5725ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               return False;
5726ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            default:
5727ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               vassert(0);
5728ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
5729ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign(arg_m, unop(dup, binop(get, getDRegI64(mreg), mkU8(index))));
5730ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else {
5731ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         res = newTemp(Ity_I64);
5732ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         arg_m = newTemp(Ity_I64);
5733ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         arg_n = newTemp(Ity_I64);
5734ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign(arg_n, getDRegI64(nreg));
5735ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         switch(size) {
5736ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 1:
5737ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               dup = Iop_Dup16x4;
5738ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               get = Iop_GetElem16x4;
5739ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               index = mreg >> 3;
5740ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               mreg &= 7;
5741ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
5742ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 2:
5743ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               dup = Iop_Dup32x2;
5744ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               get = Iop_GetElem32x2;
5745ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               index = mreg >> 4;
5746ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               mreg &= 0xf;
5747ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
5748ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 0:
5749ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 3:
5750ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               return False;
5751ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            default:
5752ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               vassert(0);
5753ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
5754ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign(arg_m, unop(dup, binop(get, getDRegI64(mreg), mkU8(index))));
5755ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
5756ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch (size) {
5757ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case 0:
5758ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case 3:
5759ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return False;
5760ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case 1:
5761ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            op = Q ? Iop_QDMulHi16Sx8 : Iop_QDMulHi16Sx4;
5762ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            op2 = Q ? Iop_CmpEQ16x8 : Iop_CmpEQ16x4;
5763ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            imm = 1LL << 15;
5764ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            imm = (imm << 16) | imm;
5765ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            imm = (imm << 32) | imm;
5766ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
5767ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case 2:
5768ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            op = Q ? Iop_QDMulHi32Sx4 : Iop_QDMulHi32Sx2;
5769ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            op2 = Q ? Iop_CmpEQ32x4 : Iop_CmpEQ32x2;
5770ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            imm = 1LL << 31;
5771ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            imm = (imm << 32) | imm;
5772ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
5773ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         default:
5774ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vassert(0);
5775ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
5776ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m)));
5777ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#ifndef DISABLE_QC_FLAG
5778ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      setFlag_QC(binop(Q ? Iop_AndV128 : Iop_And64,
5779ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       binop(op2, mkexpr(arg_n),
5780ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                  Q ? mkU128(imm) : mkU64(imm)),
5781ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       binop(op2, mkexpr(arg_m),
5782ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             Q ? mkU128(imm) : mkU64(imm))),
5783ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 Q ? mkU128(0) : mkU64(0),
5784ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 Q, condT);
5785ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
5786ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (Q)
5787ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putQReg(dreg, mkexpr(res), condT);
5788ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      else
5789ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putDRegI64(dreg, mkexpr(res), condT);
5790ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("vqdmulh.s%u %c%u, %c%u, d%u[%u]\n",
5791ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          8 << size, Q ? 'q' : 'd', dreg,
5792ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          Q ? 'q' : 'd', nreg, mreg, index);
5793ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return True;
5794ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
5795ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5796ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* VQRDMULH (scalar) */
5797ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (INSN(11,8) == BITS4(1,1,0,1)) {
5798ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IROp op ,op2, dup, get;
5799ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ULong imm;
5800ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp res, arg_m, arg_n;
5801ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (Q) {
5802ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if ((dreg & 1) || (nreg & 1))
5803ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return False;
5804ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         dreg >>= 1;
5805ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         nreg >>= 1;
5806ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         res = newTemp(Ity_V128);
5807ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         arg_m = newTemp(Ity_V128);
5808ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         arg_n = newTemp(Ity_V128);
5809ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign(arg_n, getQReg(nreg));
5810ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         switch(size) {
5811ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 1:
5812ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               dup = Iop_Dup16x8;
5813ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               get = Iop_GetElem16x4;
5814ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               index = mreg >> 3;
5815ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               mreg &= 7;
5816ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
5817ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 2:
5818ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               dup = Iop_Dup32x4;
5819ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               get = Iop_GetElem32x2;
5820ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               index = mreg >> 4;
5821ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               mreg &= 0xf;
5822ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
5823ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 0:
5824ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 3:
5825ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               return False;
5826ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            default:
5827ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               vassert(0);
5828ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
5829ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign(arg_m, unop(dup, binop(get, getDRegI64(mreg), mkU8(index))));
5830ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else {
5831ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         res = newTemp(Ity_I64);
5832ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         arg_m = newTemp(Ity_I64);
5833ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         arg_n = newTemp(Ity_I64);
5834ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign(arg_n, getDRegI64(nreg));
5835ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         switch(size) {
5836ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 1:
5837ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               dup = Iop_Dup16x4;
5838ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               get = Iop_GetElem16x4;
5839ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               index = mreg >> 3;
5840ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               mreg &= 7;
5841ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
5842ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 2:
5843ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               dup = Iop_Dup32x2;
5844ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               get = Iop_GetElem32x2;
5845ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               index = mreg >> 4;
5846ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               mreg &= 0xf;
5847ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
5848ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 0:
5849ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 3:
5850ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               return False;
5851ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            default:
5852ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               vassert(0);
5853ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
5854ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign(arg_m, unop(dup, binop(get, getDRegI64(mreg), mkU8(index))));
5855ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
5856ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch (size) {
5857ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case 0:
5858ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case 3:
5859ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return False;
5860ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case 1:
5861ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            op = Q ? Iop_QRDMulHi16Sx8 : Iop_QRDMulHi16Sx4;
5862ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            op2 = Q ? Iop_CmpEQ16x8 : Iop_CmpEQ16x4;
5863ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            imm = 1LL << 15;
5864ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            imm = (imm << 16) | imm;
5865ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            imm = (imm << 32) | imm;
5866ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
5867ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case 2:
5868ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            op = Q ? Iop_QRDMulHi32Sx4 : Iop_QRDMulHi32Sx2;
5869ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            op2 = Q ? Iop_CmpEQ32x4 : Iop_CmpEQ32x2;
5870ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            imm = 1LL << 31;
5871ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            imm = (imm << 32) | imm;
5872ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
5873ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         default:
5874ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vassert(0);
5875ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
5876ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m)));
5877ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#ifndef DISABLE_QC_FLAG
5878ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      setFlag_QC(binop(Q ? Iop_AndV128 : Iop_And64,
5879ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       binop(op2, mkexpr(arg_n),
5880ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                  Q ? mkU128(imm) : mkU64(imm)),
5881ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       binop(op2, mkexpr(arg_m),
5882ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                  Q ? mkU128(imm) : mkU64(imm))),
5883ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 Q ? mkU128(0) : mkU64(0),
5884ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 Q, condT);
5885ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
5886ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (Q)
5887ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putQReg(dreg, mkexpr(res), condT);
5888ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      else
5889ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putDRegI64(dreg, mkexpr(res), condT);
5890ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("vqrdmulh.s%u %c%u, %c%u, d%u[%u]\n",
5891ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          8 << size, Q ? 'q' : 'd', dreg,
5892ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          Q ? 'q' : 'd', nreg, mreg, index);
5893ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return True;
5894ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
5895ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5896ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return False;
5897ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  undef INSN
5898ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
5899ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5900ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* A7.4.4 Two registers and a shift amount */
5901ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
5902ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownBool dis_neon_data_2reg_and_shift ( UInt theInstr, IRTemp condT )
5903ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
5904ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt A = (theInstr >> 8) & 0xf;
5905ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt B = (theInstr >> 6) & 1;
5906ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt L = (theInstr >> 7) & 1;
5907ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt U = (theInstr >> 24) & 1;
5908ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt Q = B;
5909ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt imm6 = (theInstr >> 16) & 0x3f;
5910ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt shift_imm;
5911ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt size = 4;
5912ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt tmp;
5913ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt mreg = get_neon_m_regno(theInstr);
5914ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt dreg = get_neon_d_regno(theInstr);
5915ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ULong imm = 0;
5916ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IROp op, cvt, add = Iop_INVALID, cvt2, op_rev;
5917ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp reg_m, res, mask;
5918ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5919ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (L == 0 && ((theInstr >> 19) & 7) == 0)
5920ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* It is one reg and immediate */
5921ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return False;
5922ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5923ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tmp = (L << 6) | imm6;
5924ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (tmp & 0x40) {
5925ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      size = 3;
5926ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      shift_imm = 64 - imm6;
5927ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else if (tmp & 0x20) {
5928ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      size = 2;
5929ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      shift_imm = 64 - imm6;
5930ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else if (tmp & 0x10) {
5931ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      size = 1;
5932ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      shift_imm = 32 - imm6;
5933ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else if (tmp & 0x8) {
5934ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      size = 0;
5935ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      shift_imm = 16 - imm6;
5936ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
5937ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return False;
5938ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
5939ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5940ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (A) {
5941ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 3:
5942ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 2:
5943ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* VRSHR, VRSRA */
5944ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (shift_imm > 0) {
5945ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            IRExpr *imm_val;
5946ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            imm = 1L;
5947ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            switch (size) {
5948ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               case 0:
5949ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  imm = (imm << 8) | imm;
5950ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  /* fall through */
5951ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               case 1:
5952ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  imm = (imm << 16) | imm;
5953ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  /* fall through */
5954ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               case 2:
5955ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  imm = (imm << 32) | imm;
5956ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  /* fall through */
5957ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               case 3:
5958ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  break;
5959ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               default:
5960ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  vassert(0);
5961ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
5962ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (Q) {
5963ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               reg_m = newTemp(Ity_V128);
5964ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               res = newTemp(Ity_V128);
5965ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               imm_val = binop(Iop_64HLtoV128, mkU64(imm), mkU64(imm));
5966ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               assign(reg_m, getQReg(mreg));
5967ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               switch (size) {
5968ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 0:
5969ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     add = Iop_Add8x16;
5970ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op = U ? Iop_ShrN8x16 : Iop_SarN8x16;
5971ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     break;
5972ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 1:
5973ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     add = Iop_Add16x8;
5974ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op = U ? Iop_ShrN16x8 : Iop_SarN16x8;
5975ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     break;
5976ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 2:
5977ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     add = Iop_Add32x4;
5978ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op = U ? Iop_ShrN32x4 : Iop_SarN32x4;
5979ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     break;
5980ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 3:
5981ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     add = Iop_Add64x2;
5982ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op = U ? Iop_ShrN64x2 : Iop_SarN64x2;
5983ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     break;
5984ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  default:
5985ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     vassert(0);
5986ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               }
5987ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else {
5988ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               reg_m = newTemp(Ity_I64);
5989ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               res = newTemp(Ity_I64);
5990ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               imm_val = mkU64(imm);
5991ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               assign(reg_m, getDRegI64(mreg));
5992ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               switch (size) {
5993ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 0:
5994ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     add = Iop_Add8x8;
5995ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op = U ? Iop_ShrN8x8 : Iop_SarN8x8;
5996ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     break;
5997ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 1:
5998ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     add = Iop_Add16x4;
5999ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op = U ? Iop_ShrN16x4 : Iop_SarN16x4;
6000ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     break;
6001ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 2:
6002ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     add = Iop_Add32x2;
6003ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op = U ? Iop_ShrN32x2 : Iop_SarN32x2;
6004ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     break;
6005ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 3:
6006ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     add = Iop_Add64;
6007ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op = U ? Iop_Shr64 : Iop_Sar64;
6008ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     break;
6009ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  default:
6010ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     vassert(0);
6011ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               }
6012ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
6013ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            assign(res,
6014ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   binop(add,
6015ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         binop(op,
6016ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               mkexpr(reg_m),
6017ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               mkU8(shift_imm)),
6018ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         binop(Q ? Iop_AndV128 : Iop_And64,
6019ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               binop(op,
6020ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                     mkexpr(reg_m),
6021ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                     mkU8(shift_imm - 1)),
6022ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               imm_val)));
6023ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
6024ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (Q) {
6025ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               res = newTemp(Ity_V128);
6026ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               assign(res, getQReg(mreg));
6027ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else {
6028ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               res = newTemp(Ity_I64);
6029ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               assign(res, getDRegI64(mreg));
6030ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
6031ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
6032ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (A == 3) {
6033ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (Q) {
6034ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               putQReg(dreg, binop(add, mkexpr(res), getQReg(dreg)),
6035ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             condT);
6036ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else {
6037ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               putDRegI64(dreg, binop(add, mkexpr(res), getDRegI64(dreg)),
6038ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                condT);
6039ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
6040ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            DIP("vrsra.%c%u %c%u, %c%u, #%u\n",
6041ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                U ? 'u' : 's', 8 << size,
6042ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg, shift_imm);
6043ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
6044ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (Q) {
6045ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               putQReg(dreg, mkexpr(res), condT);
6046ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else {
6047ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               putDRegI64(dreg, mkexpr(res), condT);
6048ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
6049ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            DIP("vrshr.%c%u %c%u, %c%u, #%u\n", U ? 'u' : 's', 8 << size,
6050ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg, shift_imm);
6051ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
6052ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return True;
6053ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 1:
6054ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0:
6055ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* VSHR, VSRA */
6056ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (Q) {
6057ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            reg_m = newTemp(Ity_V128);
6058ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            assign(reg_m, getQReg(mreg));
6059ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            res = newTemp(Ity_V128);
6060ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
6061ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            reg_m = newTemp(Ity_I64);
6062ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            assign(reg_m, getDRegI64(mreg));
6063ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            res = newTemp(Ity_I64);
6064ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
6065ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (Q) {
6066ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            switch (size) {
6067ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               case 0:
6068ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  op = U ? Iop_ShrN8x16 : Iop_SarN8x16;
6069ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  add = Iop_Add8x16;
6070ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  break;
6071ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               case 1:
6072ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  op = U ? Iop_ShrN16x8 : Iop_SarN16x8;
6073ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  add = Iop_Add16x8;
6074ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  break;
6075ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               case 2:
6076ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  op = U ? Iop_ShrN32x4 : Iop_SarN32x4;
6077ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  add = Iop_Add32x4;
6078ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  break;
6079ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               case 3:
6080ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  op = U ? Iop_ShrN64x2 : Iop_SarN64x2;
6081ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  add = Iop_Add64x2;
6082ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  break;
6083ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               default:
6084ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  vassert(0);
6085ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
6086ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
6087ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            switch (size) {
6088ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               case 0:
6089ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  op =  U ? Iop_ShrN8x8 : Iop_SarN8x8;
6090ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  add = Iop_Add8x8;
6091ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  break;
6092ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               case 1:
6093ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  op = U ? Iop_ShrN16x4 : Iop_SarN16x4;
6094ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  add = Iop_Add16x4;
6095ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  break;
6096ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               case 2:
6097ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  op = U ? Iop_ShrN32x2 : Iop_SarN32x2;
6098ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  add = Iop_Add32x2;
6099ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  break;
6100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               case 3:
6101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  op = U ? Iop_Shr64 : Iop_Sar64;
6102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  add = Iop_Add64;
6103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  break;
6104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               default:
6105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  vassert(0);
6106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
6107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
6108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign(res, binop(op, mkexpr(reg_m), mkU8(shift_imm)));
6109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (A == 1) {
6110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (Q) {
6111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               putQReg(dreg, binop(add, mkexpr(res), getQReg(dreg)),
6112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             condT);
6113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else {
6114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               putDRegI64(dreg, binop(add, mkexpr(res), getDRegI64(dreg)),
6115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                condT);
6116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
6117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            DIP("vsra.%c%u %c%u, %c%u, #%u\n", U ? 'u' : 's', 8 << size,
6118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg, shift_imm);
6119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
6120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (Q) {
6121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               putQReg(dreg, mkexpr(res), condT);
6122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else {
6123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               putDRegI64(dreg, mkexpr(res), condT);
6124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
6125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            DIP("vshr.%c%u %c%u, %c%u, #%u\n", U ? 'u' : 's', 8 << size,
6126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg, shift_imm);
6127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
6128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return True;
6129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 4:
6130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* VSRI */
6131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (!U)
6132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return False;
6133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (Q) {
6134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            res = newTemp(Ity_V128);
6135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            mask = newTemp(Ity_V128);
6136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
6137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            res = newTemp(Ity_I64);
6138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            mask = newTemp(Ity_I64);
6139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
6140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         switch (size) {
6141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 0: op = Q ? Iop_ShrN8x16 : Iop_ShrN8x8; break;
6142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 1: op = Q ? Iop_ShrN16x8 : Iop_ShrN16x4; break;
6143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 2: op = Q ? Iop_ShrN32x4 : Iop_ShrN32x2; break;
6144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 3: op = Q ? Iop_ShrN64x2 : Iop_Shr64; break;
6145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            default: vassert(0);
6146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
6147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (Q) {
6148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            assign(mask, binop(op, binop(Iop_64HLtoV128,
6149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                         mkU64(0xFFFFFFFFFFFFFFFFLL),
6150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                         mkU64(0xFFFFFFFFFFFFFFFFLL)),
6151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               mkU8(shift_imm)));
6152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            assign(res, binop(Iop_OrV128,
6153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              binop(Iop_AndV128,
6154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                    getQReg(dreg),
6155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                    unop(Iop_NotV128,
6156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                         mkexpr(mask))),
6157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              binop(op,
6158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                    getQReg(mreg),
6159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                    mkU8(shift_imm))));
6160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            putQReg(dreg, mkexpr(res), condT);
6161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
6162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            assign(mask, binop(op, mkU64(0xFFFFFFFFFFFFFFFFLL),
6163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               mkU8(shift_imm)));
6164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            assign(res, binop(Iop_Or64,
6165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              binop(Iop_And64,
6166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                    getDRegI64(dreg),
6167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                    unop(Iop_Not64,
6168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                         mkexpr(mask))),
6169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              binop(op,
6170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                    getDRegI64(mreg),
6171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                    mkU8(shift_imm))));
6172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            putDRegI64(dreg, mkexpr(res), condT);
6173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
6174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("vsri.%u %c%u, %c%u, #%u\n",
6175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             8 << size, Q ? 'q' : 'd', dreg,
6176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             Q ? 'q' : 'd', mreg, shift_imm);
6177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return True;
6178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 5:
6179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (U) {
6180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* VSLI */
6181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            shift_imm = 8 * (1 << size) - shift_imm;
6182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (Q) {
6183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               res = newTemp(Ity_V128);
6184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               mask = newTemp(Ity_V128);
6185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else {
6186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               res = newTemp(Ity_I64);
6187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               mask = newTemp(Ity_I64);
6188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
6189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            switch (size) {
6190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               case 0: op = Q ? Iop_ShlN8x16 : Iop_ShlN8x8; break;
6191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               case 1: op = Q ? Iop_ShlN16x8 : Iop_ShlN16x4; break;
6192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               case 2: op = Q ? Iop_ShlN32x4 : Iop_ShlN32x2; break;
6193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               case 3: op = Q ? Iop_ShlN64x2 : Iop_Shl64; break;
6194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               default: vassert(0);
6195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
6196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (Q) {
6197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               assign(mask, binop(op, binop(Iop_64HLtoV128,
6198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                            mkU64(0xFFFFFFFFFFFFFFFFLL),
6199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                            mkU64(0xFFFFFFFFFFFFFFFFLL)),
6200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                  mkU8(shift_imm)));
6201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               assign(res, binop(Iop_OrV128,
6202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                 binop(Iop_AndV128,
6203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                       getQReg(dreg),
6204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                       unop(Iop_NotV128,
6205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                            mkexpr(mask))),
6206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                 binop(op,
6207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                       getQReg(mreg),
6208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                       mkU8(shift_imm))));
6209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               putQReg(dreg, mkexpr(res), condT);
6210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else {
6211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               assign(mask, binop(op, mkU64(0xFFFFFFFFFFFFFFFFLL),
6212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                  mkU8(shift_imm)));
6213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               assign(res, binop(Iop_Or64,
6214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                 binop(Iop_And64,
6215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                       getDRegI64(dreg),
6216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                       unop(Iop_Not64,
6217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                            mkexpr(mask))),
6218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                 binop(op,
6219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                       getDRegI64(mreg),
6220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                       mkU8(shift_imm))));
6221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               putDRegI64(dreg, mkexpr(res), condT);
6222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
6223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            DIP("vsli.%u %c%u, %c%u, #%u\n",
6224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                8 << size, Q ? 'q' : 'd', dreg,
6225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                Q ? 'q' : 'd', mreg, shift_imm);
6226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return True;
6227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
6228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* VSHL #imm */
6229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            shift_imm = 8 * (1 << size) - shift_imm;
6230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (Q) {
6231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               res = newTemp(Ity_V128);
6232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else {
6233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               res = newTemp(Ity_I64);
6234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
6235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            switch (size) {
6236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               case 0: op = Q ? Iop_ShlN8x16 : Iop_ShlN8x8; break;
6237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               case 1: op = Q ? Iop_ShlN16x8 : Iop_ShlN16x4; break;
6238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               case 2: op = Q ? Iop_ShlN32x4 : Iop_ShlN32x2; break;
6239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               case 3: op = Q ? Iop_ShlN64x2 : Iop_Shl64; break;
6240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               default: vassert(0);
6241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
6242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            assign(res, binop(op, Q ? getQReg(mreg) : getDRegI64(mreg),
6243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     mkU8(shift_imm)));
6244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (Q) {
6245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               putQReg(dreg, mkexpr(res), condT);
6246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else {
6247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               putDRegI64(dreg, mkexpr(res), condT);
6248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
6249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            DIP("vshl.i%u %c%u, %c%u, #%u\n",
6250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                8 << size, Q ? 'q' : 'd', dreg,
6251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                Q ? 'q' : 'd', mreg, shift_imm);
6252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return True;
6253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
6254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
6255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 6:
6256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 7:
6257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* VQSHL, VQSHLU */
6258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         shift_imm = 8 * (1 << size) - shift_imm;
6259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (U) {
6260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (A & 1) {
6261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               switch (size) {
6262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 0:
6263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op = Q ? Iop_QShlN8x16 : Iop_QShlN8x8;
6264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op_rev = Q ? Iop_ShrN8x16 : Iop_ShrN8x8;
6265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     break;
6266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 1:
6267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op = Q ? Iop_QShlN16x8 : Iop_QShlN16x4;
6268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op_rev = Q ? Iop_ShrN16x8 : Iop_ShrN16x4;
6269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     break;
6270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 2:
6271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op = Q ? Iop_QShlN32x4 : Iop_QShlN32x2;
6272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op_rev = Q ? Iop_ShrN32x4 : Iop_ShrN32x2;
6273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     break;
6274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 3:
6275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op = Q ? Iop_QShlN64x2 : Iop_QShlN64x1;
6276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op_rev = Q ? Iop_ShrN64x2 : Iop_Shr64;
6277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     break;
6278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  default:
6279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     vassert(0);
6280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               }
6281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               DIP("vqshl.u%u %c%u, %c%u, #%u\n",
6282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   8 << size,
6283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg, shift_imm);
6284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else {
6285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               switch (size) {
6286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 0:
6287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op = Q ? Iop_QShlN8Sx16 : Iop_QShlN8Sx8;
6288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op_rev = Q ? Iop_ShrN8x16 : Iop_ShrN8x8;
6289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     break;
6290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 1:
6291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op = Q ? Iop_QShlN16Sx8 : Iop_QShlN16Sx4;
6292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op_rev = Q ? Iop_ShrN16x8 : Iop_ShrN16x4;
6293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     break;
6294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 2:
6295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op = Q ? Iop_QShlN32Sx4 : Iop_QShlN32Sx2;
6296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op_rev = Q ? Iop_ShrN32x4 : Iop_ShrN32x2;
6297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     break;
6298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 3:
6299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op = Q ? Iop_QShlN64Sx2 : Iop_QShlN64Sx1;
6300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op_rev = Q ? Iop_ShrN64x2 : Iop_Shr64;
6301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     break;
6302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  default:
6303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     vassert(0);
6304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               }
6305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               DIP("vqshlu.s%u %c%u, %c%u, #%u\n",
6306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   8 << size,
6307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg, shift_imm);
6308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
6309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
6310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (!(A & 1))
6311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               return False;
6312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            switch (size) {
6313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               case 0:
6314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  op = Q ? Iop_QSalN8x16 : Iop_QSalN8x8;
6315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  op_rev = Q ? Iop_SarN8x16 : Iop_SarN8x8;
6316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  break;
6317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               case 1:
6318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  op = Q ? Iop_QSalN16x8 : Iop_QSalN16x4;
6319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  op_rev = Q ? Iop_SarN16x8 : Iop_SarN16x4;
6320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  break;
6321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               case 2:
6322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  op = Q ? Iop_QSalN32x4 : Iop_QSalN32x2;
6323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  op_rev = Q ? Iop_SarN32x4 : Iop_SarN32x2;
6324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  break;
6325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               case 3:
6326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  op = Q ? Iop_QSalN64x2 : Iop_QSalN64x1;
6327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  op_rev = Q ? Iop_SarN64x2 : Iop_Sar64;
6328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  break;
6329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               default:
6330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  vassert(0);
6331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
6332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            DIP("vqshl.s%u %c%u, %c%u, #%u\n",
6333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                8 << size,
6334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg, shift_imm);
6335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
6336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (Q) {
6337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            tmp = newTemp(Ity_V128);
6338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            res = newTemp(Ity_V128);
6339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            reg_m = newTemp(Ity_V128);
6340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            assign(reg_m, getQReg(mreg));
6341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
6342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            tmp = newTemp(Ity_I64);
6343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            res = newTemp(Ity_I64);
6344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            reg_m = newTemp(Ity_I64);
6345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            assign(reg_m, getDRegI64(mreg));
6346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
6347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign(res, binop(op, mkexpr(reg_m), mkU8(shift_imm)));
6348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#ifndef DISABLE_QC_FLAG
6349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign(tmp, binop(op_rev, mkexpr(res), mkU8(shift_imm)));
6350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         setFlag_QC(mkexpr(tmp), mkexpr(reg_m), Q, condT);
6351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
6352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (Q)
6353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            putQReg(dreg, mkexpr(res), condT);
6354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         else
6355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            putDRegI64(dreg, mkexpr(res), condT);
6356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return True;
6357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 8:
6358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (!U) {
6359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (L == 1)
6360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               return False;
6361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            size++;
6362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            dreg = ((theInstr >> 18) & 0x10) | ((theInstr >> 12) & 0xF);
6363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            mreg = ((theInstr >> 1) & 0x10) | (theInstr & 0xF);
6364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (mreg & 1)
6365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               return False;
6366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            mreg >>= 1;
6367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (!B) {
6368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               /* VSHRN*/
6369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               IROp narOp;
6370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               reg_m = newTemp(Ity_V128);
6371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               assign(reg_m, getQReg(mreg));
6372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               res = newTemp(Ity_I64);
6373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               switch (size) {
6374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 1:
6375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op = Iop_ShrN16x8;
6376b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                     narOp = Iop_NarrowUn16to8x8;
6377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     break;
6378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 2:
6379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op = Iop_ShrN32x4;
6380b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                     narOp = Iop_NarrowUn32to16x4;
6381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     break;
6382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 3:
6383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op = Iop_ShrN64x2;
6384b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                     narOp = Iop_NarrowUn64to32x2;
6385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     break;
6386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  default:
6387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     vassert(0);
6388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               }
6389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               assign(res, unop(narOp,
6390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                binop(op,
6391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                      mkexpr(reg_m),
6392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                      mkU8(shift_imm))));
6393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               putDRegI64(dreg, mkexpr(res), condT);
6394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               DIP("vshrn.i%u d%u, q%u, #%u\n", 8 << size, dreg, mreg,
6395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   shift_imm);
6396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               return True;
6397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else {
6398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               /* VRSHRN   */
6399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               IROp addOp, shOp, narOp;
6400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               IRExpr *imm_val;
6401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               reg_m = newTemp(Ity_V128);
6402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               assign(reg_m, getQReg(mreg));
6403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               res = newTemp(Ity_I64);
6404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               imm = 1L;
6405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               switch (size) {
6406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 0: imm = (imm <<  8) | imm; /* fall through */
6407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 1: imm = (imm << 16) | imm; /* fall through */
6408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 2: imm = (imm << 32) | imm; /* fall through */
6409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 3: break;
6410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  default: vassert(0);
6411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               }
6412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               imm_val = binop(Iop_64HLtoV128, mkU64(imm), mkU64(imm));
6413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               switch (size) {
6414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 1:
6415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     addOp = Iop_Add16x8;
6416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     shOp = Iop_ShrN16x8;
6417b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                     narOp = Iop_NarrowUn16to8x8;
6418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     break;
6419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 2:
6420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     addOp = Iop_Add32x4;
6421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     shOp = Iop_ShrN32x4;
6422b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                     narOp = Iop_NarrowUn32to16x4;
6423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     break;
6424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 3:
6425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     addOp = Iop_Add64x2;
6426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     shOp = Iop_ShrN64x2;
6427b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                     narOp = Iop_NarrowUn64to32x2;
6428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     break;
6429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  default:
6430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     vassert(0);
6431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               }
6432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               assign(res, unop(narOp,
6433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                binop(addOp,
6434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                      binop(shOp,
6435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                            mkexpr(reg_m),
6436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                            mkU8(shift_imm)),
6437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                      binop(Iop_AndV128,
6438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                            binop(shOp,
6439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                                  mkexpr(reg_m),
6440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                                  mkU8(shift_imm - 1)),
6441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                            imm_val))));
6442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               putDRegI64(dreg, mkexpr(res), condT);
6443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               if (shift_imm == 0) {
6444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  DIP("vmov%u d%u, q%u, #%u\n", 8 << size, dreg, mreg,
6445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      shift_imm);
6446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               } else {
6447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  DIP("vrshrn.i%u d%u, q%u, #%u\n", 8 << size, dreg, mreg,
6448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      shift_imm);
6449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               }
6450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               return True;
6451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
6452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
6453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* fall through */
6454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
6455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 9:
6456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         dreg = ((theInstr >> 18) & 0x10) | ((theInstr >> 12) & 0xF);
6457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         mreg = ((theInstr >>  1) & 0x10) | (theInstr & 0xF);
6458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (mreg & 1)
6459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return False;
6460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         mreg >>= 1;
6461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         size++;
6462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if ((theInstr >> 8) & 1) {
6463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            switch (size) {
6464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               case 1:
6465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  op = U ? Iop_ShrN16x8 : Iop_SarN16x8;
6466b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                  cvt = U ? Iop_QNarrowUn16Uto8Ux8 : Iop_QNarrowUn16Sto8Sx8;
6467b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                  cvt2 = U ? Iop_Widen8Uto16x8 : Iop_Widen8Sto16x8;
6468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  break;
6469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               case 2:
6470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  op = U ? Iop_ShrN32x4 : Iop_SarN32x4;
6471b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                  cvt = U ? Iop_QNarrowUn32Uto16Ux4 : Iop_QNarrowUn32Sto16Sx4;
6472b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                  cvt2 = U ? Iop_Widen16Uto32x4 : Iop_Widen16Sto32x4;
6473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  break;
6474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               case 3:
6475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  op = U ? Iop_ShrN64x2 : Iop_SarN64x2;
6476b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                  cvt = U ? Iop_QNarrowUn64Uto32Ux2 : Iop_QNarrowUn64Sto32Sx2;
6477b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                  cvt2 = U ? Iop_Widen32Uto64x2 : Iop_Widen32Sto64x2;
6478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  break;
6479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               default:
6480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  vassert(0);
6481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
6482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            DIP("vq%sshrn.%c%u d%u, q%u, #%u\n", B ? "r" : "",
6483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                U ? 'u' : 's', 8 << size, dreg, mreg, shift_imm);
6484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
6485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vassert(U);
6486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            switch (size) {
6487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               case 1:
6488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  op = Iop_SarN16x8;
6489b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                  cvt = Iop_QNarrowUn16Sto8Ux8;
6490b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                  cvt2 = Iop_Widen8Uto16x8;
6491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  break;
6492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               case 2:
6493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  op = Iop_SarN32x4;
6494b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                  cvt = Iop_QNarrowUn32Sto16Ux4;
6495b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                  cvt2 = Iop_Widen16Uto32x4;
6496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  break;
6497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               case 3:
6498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  op = Iop_SarN64x2;
6499b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                  cvt = Iop_QNarrowUn64Sto32Ux2;
6500b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                  cvt2 = Iop_Widen32Uto64x2;
6501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  break;
6502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               default:
6503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  vassert(0);
6504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
6505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            DIP("vq%sshrun.s%u d%u, q%u, #%u\n", B ? "r" : "",
6506ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                8 << size, dreg, mreg, shift_imm);
6507ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
6508ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (B) {
6509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (shift_imm > 0) {
6510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               imm = 1;
6511ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               switch (size) {
6512ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 1: imm = (imm << 16) | imm; /* fall through */
6513ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 2: imm = (imm << 32) | imm; /* fall through */
6514ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 3: break;
6515ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 0: default: vassert(0);
6516ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               }
6517ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               switch (size) {
6518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 1: add = Iop_Add16x8; break;
6519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 2: add = Iop_Add32x4; break;
6520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 3: add = Iop_Add64x2; break;
6521ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 0: default: vassert(0);
6522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               }
6523ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
6524ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
6525ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         reg_m = newTemp(Ity_V128);
6526ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         res = newTemp(Ity_V128);
6527ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign(reg_m, getQReg(mreg));
6528ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (B) {
6529ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* VQRSHRN, VQRSHRUN */
6530ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            assign(res, binop(add,
6531ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              binop(op, mkexpr(reg_m), mkU8(shift_imm)),
6532ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              binop(Iop_AndV128,
6533ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                    binop(op,
6534ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                          mkexpr(reg_m),
6535ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                          mkU8(shift_imm - 1)),
6536ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                    mkU128(imm))));
6537ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
6538ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* VQSHRN, VQSHRUN */
6539ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            assign(res, binop(op, mkexpr(reg_m), mkU8(shift_imm)));
6540ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
6541ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#ifndef DISABLE_QC_FLAG
6542ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         setFlag_QC(unop(cvt2, unop(cvt, mkexpr(res))), mkexpr(res),
6543ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    True, condT);
6544ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
6545ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putDRegI64(dreg, unop(cvt, mkexpr(res)), condT);
6546ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return True;
6547ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 10:
6548ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* VSHLL
6549ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            VMOVL ::= VSHLL #0 */
6550ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (B)
6551ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return False;
6552ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (dreg & 1)
6553ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return False;
6554ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         dreg >>= 1;
6555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         shift_imm = (8 << size) - shift_imm;
6556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         res = newTemp(Ity_V128);
6557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         switch (size) {
6558ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 0:
6559ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               op = Iop_ShlN16x8;
6560b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               cvt = U ? Iop_Widen8Uto16x8 : Iop_Widen8Sto16x8;
6561ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
6562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 1:
6563ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               op = Iop_ShlN32x4;
6564b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               cvt = U ? Iop_Widen16Uto32x4 : Iop_Widen16Sto32x4;
6565ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
6566ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 2:
6567ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               op = Iop_ShlN64x2;
6568b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               cvt = U ? Iop_Widen32Uto64x2 : Iop_Widen32Sto64x2;
6569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
6570ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 3:
6571ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               return False;
6572ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            default:
6573ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               vassert(0);
6574ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
6575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign(res, binop(op, unop(cvt, getDRegI64(mreg)), mkU8(shift_imm)));
6576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putQReg(dreg, mkexpr(res), condT);
6577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (shift_imm == 0) {
6578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            DIP("vmovl.%c%u q%u, d%u\n", U ? 'u' : 's', 8 << size,
6579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                dreg, mreg);
6580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
6581ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            DIP("vshll.%c%u q%u, d%u, #%u\n", U ? 'u' : 's', 8 << size,
6582ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                dreg, mreg, shift_imm);
6583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
6584ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return True;
6585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 14:
6586ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 15:
6587ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* VCVT floating-point <-> fixed-point */
6588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if ((theInstr >> 8) & 1) {
6589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (U) {
6590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               op = Q ? Iop_F32ToFixed32Ux4_RZ : Iop_F32ToFixed32Ux2_RZ;
6591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else {
6592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               op = Q ? Iop_F32ToFixed32Sx4_RZ : Iop_F32ToFixed32Sx2_RZ;
6593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
6594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            DIP("vcvt.%c32.f32 %c%u, %c%u, #%u\n", U ? 'u' : 's',
6595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg,
6596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                64 - ((theInstr >> 16) & 0x3f));
6597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
6598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (U) {
6599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               op = Q ? Iop_Fixed32UToF32x4_RN : Iop_Fixed32UToF32x2_RN;
6600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else {
6601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               op = Q ? Iop_Fixed32SToF32x4_RN : Iop_Fixed32SToF32x2_RN;
6602ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
6603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            DIP("vcvt.f32.%c32 %c%u, %c%u, #%u\n", U ? 'u' : 's',
6604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg,
6605ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                64 - ((theInstr >> 16) & 0x3f));
6606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
6607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (((theInstr >> 21) & 1) == 0)
6608ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return False;
6609ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (Q) {
6610ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            putQReg(dreg, binop(op, getQReg(mreg),
6611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     mkU8(64 - ((theInstr >> 16) & 0x3f))), condT);
6612ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
6613ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            putDRegI64(dreg, binop(op, getDRegI64(mreg),
6614ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       mkU8(64 - ((theInstr >> 16) & 0x3f))), condT);
6615ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
6616ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return True;
6617ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
6618ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return False;
6619ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6620ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
6621ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return False;
6622ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
6623ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6624ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* A7.4.5 Two registers, miscellaneous */
6625ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
6626ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownBool dis_neon_data_2reg_misc ( UInt theInstr, IRTemp condT )
6627ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
6628ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt A = (theInstr >> 16) & 3;
6629ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt B = (theInstr >> 6) & 0x1f;
6630ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt Q = (theInstr >> 6) & 1;
6631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt U = (theInstr >> 24) & 1;
6632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt size = (theInstr >> 18) & 3;
6633ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt dreg = get_neon_d_regno(theInstr);
6634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt mreg = get_neon_m_regno(theInstr);
6635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt F = (theInstr >> 10) & 1;
6636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp arg_d;
6637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp arg_m;
6638ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp res;
6639ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (A) {
6640ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0:
6641ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (Q) {
6642ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            arg_m = newTemp(Ity_V128);
6643ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            res = newTemp(Ity_V128);
6644ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            assign(arg_m, getQReg(mreg));
6645ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
6646ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            arg_m = newTemp(Ity_I64);
6647ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            res = newTemp(Ity_I64);
6648ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            assign(arg_m, getDRegI64(mreg));
6649ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
6650ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         switch (B >> 1) {
6651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 0: {
6652ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               /* VREV64 */
6653ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               IROp op;
6654ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               switch (size) {
6655ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 0:
6656ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op = Q ? Iop_Reverse64_8x16 : Iop_Reverse64_8x8;
6657ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     break;
6658ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 1:
6659ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op = Q ? Iop_Reverse64_16x8 : Iop_Reverse64_16x4;
6660ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     break;
6661ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 2:
6662ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op = Q ? Iop_Reverse64_32x4 : Iop_Reverse64_32x2;
6663ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     break;
6664ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 3:
6665ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     return False;
6666ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  default:
6667ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     vassert(0);
6668ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               }
6669ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               assign(res, unop(op, mkexpr(arg_m)));
6670ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               DIP("vrev64.%u %c%u, %c%u\n", 8 << size,
6671ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg);
6672ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
6673ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
6674ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 1: {
6675ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               /* VREV32 */
6676ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               IROp op;
6677ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               switch (size) {
6678ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 0:
6679ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op = Q ? Iop_Reverse32_8x16 : Iop_Reverse32_8x8;
6680ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     break;
6681ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 1:
6682ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op = Q ? Iop_Reverse32_16x8 : Iop_Reverse32_16x4;
6683ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     break;
6684ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 2:
6685ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 3:
6686ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     return False;
6687ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  default:
6688ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     vassert(0);
6689ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               }
6690ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               assign(res, unop(op, mkexpr(arg_m)));
6691ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               DIP("vrev32.%u %c%u, %c%u\n", 8 << size,
6692ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg);
6693ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
6694ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
6695ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 2: {
6696ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               /* VREV16 */
6697ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               IROp op;
6698ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               switch (size) {
6699ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 0:
6700ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op = Q ? Iop_Reverse16_8x16 : Iop_Reverse16_8x8;
6701ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     break;
6702ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 1:
6703ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 2:
6704ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 3:
6705ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     return False;
6706ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  default:
6707ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     vassert(0);
6708ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               }
6709ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               assign(res, unop(op, mkexpr(arg_m)));
6710ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               DIP("vrev16.%u %c%u, %c%u\n", 8 << size,
6711ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg);
6712ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
6713ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
6714ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 3:
6715ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               return False;
6716ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 4:
6717ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 5: {
6718ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               /* VPADDL */
6719ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               IROp op;
6720ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               U = (theInstr >> 7) & 1;
6721ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               if (Q) {
6722ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  switch (size) {
6723ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     case 0: op = U ? Iop_PwAddL8Ux16 : Iop_PwAddL8Sx16; break;
6724ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     case 1: op = U ? Iop_PwAddL16Ux8 : Iop_PwAddL16Sx8; break;
6725ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     case 2: op = U ? Iop_PwAddL32Ux4 : Iop_PwAddL32Sx4; break;
6726ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     case 3: return False;
6727ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     default: vassert(0);
6728ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  }
6729ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               } else {
6730ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  switch (size) {
6731ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     case 0: op = U ? Iop_PwAddL8Ux8  : Iop_PwAddL8Sx8;  break;
6732ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     case 1: op = U ? Iop_PwAddL16Ux4 : Iop_PwAddL16Sx4; break;
6733ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     case 2: op = U ? Iop_PwAddL32Ux2 : Iop_PwAddL32Sx2; break;
6734ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     case 3: return False;
6735ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     default: vassert(0);
6736ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  }
6737ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               }
6738ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               assign(res, unop(op, mkexpr(arg_m)));
6739ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               DIP("vpaddl.%c%u %c%u, %c%u\n", U ? 'u' : 's', 8 << size,
6740ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg);
6741ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
6742ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
6743ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 6:
6744ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 7:
6745ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               return False;
6746ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 8: {
6747ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               /* VCLS */
6748ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               IROp op;
6749ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               switch (size) {
6750ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 0: op = Q ? Iop_Cls8Sx16 : Iop_Cls8Sx8; break;
6751ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 1: op = Q ? Iop_Cls16Sx8 : Iop_Cls16Sx4; break;
6752ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 2: op = Q ? Iop_Cls32Sx4 : Iop_Cls32Sx2; break;
6753ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 3: return False;
6754ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  default: vassert(0);
6755ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               }
6756ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               assign(res, unop(op, mkexpr(arg_m)));
6757ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               DIP("vcls.s%u %c%u, %c%u\n", 8 << size, Q ? 'q' : 'd', dreg,
6758ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   Q ? 'q' : 'd', mreg);
6759ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
6760ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
6761ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 9: {
6762ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               /* VCLZ */
6763ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               IROp op;
6764ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               switch (size) {
6765ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 0: op = Q ? Iop_Clz8Sx16 : Iop_Clz8Sx8; break;
6766ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 1: op = Q ? Iop_Clz16Sx8 : Iop_Clz16Sx4; break;
6767ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 2: op = Q ? Iop_Clz32Sx4 : Iop_Clz32Sx2; break;
6768ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 3: return False;
6769ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  default: vassert(0);
6770ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               }
6771ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               assign(res, unop(op, mkexpr(arg_m)));
6772ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               DIP("vclz.i%u %c%u, %c%u\n", 8 << size, Q ? 'q' : 'd', dreg,
6773ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   Q ? 'q' : 'd', mreg);
6774ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
6775ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
6776ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 10:
6777ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               /* VCNT */
6778ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               assign(res, unop(Q ? Iop_Cnt8x16 : Iop_Cnt8x8, mkexpr(arg_m)));
6779ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               DIP("vcnt.8 %c%u, %c%u\n", Q ? 'q' : 'd', dreg, Q ? 'q' : 'd',
6780ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   mreg);
6781ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
6782ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 11:
6783ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               /* VMVN */
6784ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               if (Q)
6785ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  assign(res, unop(Iop_NotV128, mkexpr(arg_m)));
6786ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               else
6787ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  assign(res, unop(Iop_Not64, mkexpr(arg_m)));
6788ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               DIP("vmvn %c%u, %c%u\n", Q ? 'q' : 'd', dreg, Q ? 'q' : 'd',
6789ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   mreg);
6790ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
6791ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 12:
6792ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 13: {
6793ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               /* VPADAL */
6794ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               IROp op, add_op;
6795ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               U = (theInstr >> 7) & 1;
6796ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               if (Q) {
6797ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  switch (size) {
6798ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     case 0:
6799ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        op = U ? Iop_PwAddL8Ux16 : Iop_PwAddL8Sx16;
6800ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        add_op = Iop_Add16x8;
6801ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        break;
6802ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     case 1:
6803ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        op = U ? Iop_PwAddL16Ux8 : Iop_PwAddL16Sx8;
6804ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        add_op = Iop_Add32x4;
6805ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        break;
6806ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     case 2:
6807ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        op = U ? Iop_PwAddL32Ux4 : Iop_PwAddL32Sx4;
6808ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        add_op = Iop_Add64x2;
6809ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        break;
6810ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     case 3:
6811ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        return False;
6812ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     default:
6813ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        vassert(0);
6814ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  }
6815ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               } else {
6816ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  switch (size) {
6817ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     case 0:
6818ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        op = U ? Iop_PwAddL8Ux8 : Iop_PwAddL8Sx8;
6819ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        add_op = Iop_Add16x4;
6820ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        break;
6821ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     case 1:
6822ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        op = U ? Iop_PwAddL16Ux4 : Iop_PwAddL16Sx4;
6823ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        add_op = Iop_Add32x2;
6824ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        break;
6825ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     case 2:
6826ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        op = U ? Iop_PwAddL32Ux2 : Iop_PwAddL32Sx2;
6827ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        add_op = Iop_Add64;
6828ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        break;
6829ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     case 3:
6830ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        return False;
6831ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     default:
6832ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        vassert(0);
6833ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  }
6834ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               }
6835ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               if (Q) {
6836ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  arg_d = newTemp(Ity_V128);
6837ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  assign(arg_d, getQReg(dreg));
6838ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               } else {
6839ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  arg_d = newTemp(Ity_I64);
6840ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  assign(arg_d, getDRegI64(dreg));
6841ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               }
6842ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               assign(res, binop(add_op, unop(op, mkexpr(arg_m)),
6843ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                         mkexpr(arg_d)));
6844ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               DIP("vpadal.%c%u %c%u, %c%u\n", U ? 'u' : 's', 8 << size,
6845ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg);
6846ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
6847ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
6848ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 14: {
6849ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               /* VQABS */
6850ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               IROp op_sub, op_qsub, op_cmp;
6851ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               IRTemp mask, tmp;
6852ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               IRExpr *zero1, *zero2;
6853ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               IRExpr *neg, *neg2;
6854ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               if (Q) {
6855ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  zero1 = binop(Iop_64HLtoV128, mkU64(0), mkU64(0));
6856ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  zero2 = binop(Iop_64HLtoV128, mkU64(0), mkU64(0));
6857ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  mask = newTemp(Ity_V128);
6858ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  tmp = newTemp(Ity_V128);
6859ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               } else {
6860ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  zero1 = mkU64(0);
6861ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  zero2 = mkU64(0);
6862ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  mask = newTemp(Ity_I64);
6863ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  tmp = newTemp(Ity_I64);
6864ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               }
6865ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               switch (size) {
6866ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 0:
6867ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op_sub = Q ? Iop_Sub8x16 : Iop_Sub8x8;
6868ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op_qsub = Q ? Iop_QSub8Sx16 : Iop_QSub8Sx8;
6869ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op_cmp = Q ? Iop_CmpGT8Sx16 : Iop_CmpGT8Sx8;
6870ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     break;
6871ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 1:
6872ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op_sub = Q ? Iop_Sub16x8 : Iop_Sub16x4;
6873ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op_qsub = Q ? Iop_QSub16Sx8 : Iop_QSub16Sx4;
6874ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op_cmp = Q ? Iop_CmpGT16Sx8 : Iop_CmpGT16Sx4;
6875ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     break;
6876ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 2:
6877ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op_sub = Q ? Iop_Sub32x4 : Iop_Sub32x2;
6878ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op_qsub = Q ? Iop_QSub32Sx4 : Iop_QSub32Sx2;
6879ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op_cmp = Q ? Iop_CmpGT32Sx4 : Iop_CmpGT32Sx2;
6880ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     break;
6881ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 3:
6882ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     return False;
6883ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  default:
6884ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     vassert(0);
6885ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               }
6886ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               assign(mask, binop(op_cmp, mkexpr(arg_m), zero1));
6887ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               neg = binop(op_qsub, zero2, mkexpr(arg_m));
6888ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               neg2 = binop(op_sub, zero2, mkexpr(arg_m));
6889ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               assign(res, binop(Q ? Iop_OrV128 : Iop_Or64,
6890ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                 binop(Q ? Iop_AndV128 : Iop_And64,
6891ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                       mkexpr(mask),
6892ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                       mkexpr(arg_m)),
6893ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                 binop(Q ? Iop_AndV128 : Iop_And64,
6894ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                       unop(Q ? Iop_NotV128 : Iop_Not64,
6895ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                            mkexpr(mask)),
6896ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                       neg)));
6897ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#ifndef DISABLE_QC_FLAG
6898ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               assign(tmp, binop(Q ? Iop_OrV128 : Iop_Or64,
6899ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                 binop(Q ? Iop_AndV128 : Iop_And64,
6900ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                       mkexpr(mask),
6901ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                       mkexpr(arg_m)),
6902ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                 binop(Q ? Iop_AndV128 : Iop_And64,
6903ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                       unop(Q ? Iop_NotV128 : Iop_Not64,
6904ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                            mkexpr(mask)),
6905ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                       neg2)));
6906ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               setFlag_QC(mkexpr(res), mkexpr(tmp), Q, condT);
6907ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
6908ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               DIP("vqabs.s%u %c%u, %c%u\n", 8 << size, Q ? 'q' : 'd', dreg,
6909ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   Q ? 'q' : 'd', mreg);
6910ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
6911ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
6912ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 15: {
6913ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               /* VQNEG */
6914ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               IROp op, op2;
6915ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               IRExpr *zero;
6916ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               if (Q) {
6917ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  zero = binop(Iop_64HLtoV128, mkU64(0), mkU64(0));
6918ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               } else {
6919ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  zero = mkU64(0);
6920ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               }
6921ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               switch (size) {
6922ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 0:
6923ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op = Q ? Iop_QSub8Sx16 : Iop_QSub8Sx8;
6924ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op2 = Q ? Iop_Sub8x16 : Iop_Sub8x8;
6925ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     break;
6926ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 1:
6927ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op = Q ? Iop_QSub16Sx8 : Iop_QSub16Sx4;
6928ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op2 = Q ? Iop_Sub16x8 : Iop_Sub16x4;
6929ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     break;
6930ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 2:
6931ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op = Q ? Iop_QSub32Sx4 : Iop_QSub32Sx2;
6932ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op2 = Q ? Iop_Sub32x4 : Iop_Sub32x2;
6933ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     break;
6934ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 3:
6935ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     return False;
6936ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  default:
6937ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     vassert(0);
6938ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               }
6939ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               assign(res, binop(op, zero, mkexpr(arg_m)));
6940ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#ifndef DISABLE_QC_FLAG
6941ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               setFlag_QC(mkexpr(res), binop(op2, zero, mkexpr(arg_m)),
6942ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          Q, condT);
6943ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
6944ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               DIP("vqneg.s%u %c%u, %c%u\n", 8 << size, Q ? 'q' : 'd', dreg,
6945ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   Q ? 'q' : 'd', mreg);
6946ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
6947ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
6948ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            default:
6949ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               vassert(0);
6950ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
6951ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (Q) {
6952ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            putQReg(dreg, mkexpr(res), condT);
6953ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
6954ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            putDRegI64(dreg, mkexpr(res), condT);
6955ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
6956ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return True;
6957ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 1:
6958ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (Q) {
6959ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            arg_m = newTemp(Ity_V128);
6960ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            res = newTemp(Ity_V128);
6961ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            assign(arg_m, getQReg(mreg));
6962ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
6963ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            arg_m = newTemp(Ity_I64);
6964ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            res = newTemp(Ity_I64);
6965ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            assign(arg_m, getDRegI64(mreg));
6966ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
6967ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         switch ((B >> 1) & 0x7) {
6968ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 0: {
6969ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               /* VCGT #0 */
6970ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               IRExpr *zero;
6971ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               IROp op;
6972ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               if (Q) {
6973ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  zero = binop(Iop_64HLtoV128, mkU64(0), mkU64(0));
6974ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               } else {
6975ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  zero = mkU64(0);
6976ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               }
6977ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               if (F) {
6978ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  switch (size) {
6979ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     case 0: case 1: case 3: return False;
6980ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     case 2: op = Q ? Iop_CmpGT32Fx4 : Iop_CmpGT32Fx2; break;
6981ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     default: vassert(0);
6982ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  }
6983ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               } else {
6984ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  switch (size) {
6985ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     case 0: op = Q ? Iop_CmpGT8Sx16 : Iop_CmpGT8Sx8; break;
6986ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     case 1: op = Q ? Iop_CmpGT16Sx8 : Iop_CmpGT16Sx4; break;
6987ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     case 2: op = Q ? Iop_CmpGT32Sx4 : Iop_CmpGT32Sx2; break;
6988ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     case 3: return False;
6989ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     default: vassert(0);
6990ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  }
6991ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               }
6992ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               assign(res, binop(op, mkexpr(arg_m), zero));
6993ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               DIP("vcgt.%c%u %c%u, %c%u, #0\n", F ? 'f' : 's', 8 << size,
6994ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg);
6995ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
6996ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
6997ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 1: {
6998ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               /* VCGE #0 */
6999ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               IROp op;
7000ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               IRExpr *zero;
7001ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               if (Q) {
7002ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  zero = binop(Iop_64HLtoV128, mkU64(0), mkU64(0));
7003ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               } else {
7004ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  zero = mkU64(0);
7005ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               }
7006ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               if (F) {
7007ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  switch (size) {
7008ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     case 0: case 1: case 3: return False;
7009ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     case 2: op = Q ? Iop_CmpGE32Fx4 : Iop_CmpGE32Fx2; break;
7010ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     default: vassert(0);
7011ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  }
7012ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  assign(res, binop(op, mkexpr(arg_m), zero));
7013ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               } else {
7014ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  switch (size) {
7015ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     case 0: op = Q ? Iop_CmpGT8Sx16 : Iop_CmpGT8Sx8; break;
7016ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     case 1: op = Q ? Iop_CmpGT16Sx8 : Iop_CmpGT16Sx4; break;
7017ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     case 2: op = Q ? Iop_CmpGT32Sx4 : Iop_CmpGT32Sx2; break;
7018ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     case 3: return False;
7019ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     default: vassert(0);
7020ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  }
7021ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  assign(res, unop(Q ? Iop_NotV128 : Iop_Not64,
7022ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                   binop(op, zero, mkexpr(arg_m))));
7023ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               }
7024ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               DIP("vcge.%c%u %c%u, %c%u, #0\n", F ? 'f' : 's', 8 << size,
7025ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg);
7026ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
7027ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
7028ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 2: {
7029ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               /* VCEQ #0 */
7030ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               IROp op;
7031ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               IRExpr *zero;
7032ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               if (F) {
7033ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  if (Q) {
7034ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     zero = binop(Iop_64HLtoV128, mkU64(0), mkU64(0));
7035ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  } else {
7036ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     zero = mkU64(0);
7037ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  }
7038ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  switch (size) {
7039ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     case 0: case 1: case 3: return False;
7040ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     case 2: op = Q ? Iop_CmpEQ32Fx4 : Iop_CmpEQ32Fx2; break;
7041ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     default: vassert(0);
7042ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  }
7043ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  assign(res, binop(op, zero, mkexpr(arg_m)));
7044ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               } else {
7045ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  switch (size) {
7046ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     case 0: op = Q ? Iop_CmpNEZ8x16 : Iop_CmpNEZ8x8; break;
7047ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     case 1: op = Q ? Iop_CmpNEZ16x8 : Iop_CmpNEZ16x4; break;
7048ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     case 2: op = Q ? Iop_CmpNEZ32x4 : Iop_CmpNEZ32x2; break;
7049ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     case 3: return False;
7050ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     default: vassert(0);
7051ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  }
7052ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  assign(res, unop(Q ? Iop_NotV128 : Iop_Not64,
7053ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                   unop(op, mkexpr(arg_m))));
7054ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               }
7055ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               DIP("vceq.%c%u %c%u, %c%u, #0\n", F ? 'f' : 'i', 8 << size,
7056ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg);
7057ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
7058ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
7059ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 3: {
7060ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               /* VCLE #0 */
7061ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               IRExpr *zero;
7062ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               IROp op;
7063ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               if (Q) {
7064ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  zero = binop(Iop_64HLtoV128, mkU64(0), mkU64(0));
7065ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               } else {
7066ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  zero = mkU64(0);
7067ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               }
7068ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               if (F) {
7069ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  switch (size) {
7070ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     case 0: case 1: case 3: return False;
7071ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     case 2: op = Q ? Iop_CmpGE32Fx4 : Iop_CmpGE32Fx2; break;
7072ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     default: vassert(0);
7073ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  }
7074ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  assign(res, binop(op, zero, mkexpr(arg_m)));
7075ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               } else {
7076ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  switch (size) {
7077ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     case 0: op = Q ? Iop_CmpGT8Sx16 : Iop_CmpGT8Sx8; break;
7078ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     case 1: op = Q ? Iop_CmpGT16Sx8 : Iop_CmpGT16Sx4; break;
7079ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     case 2: op = Q ? Iop_CmpGT32Sx4 : Iop_CmpGT32Sx2; break;
7080ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     case 3: return False;
7081ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     default: vassert(0);
7082ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  }
7083ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  assign(res, unop(Q ? Iop_NotV128 : Iop_Not64,
7084ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                   binop(op, mkexpr(arg_m), zero)));
7085ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               }
7086ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               DIP("vcle.%c%u %c%u, %c%u, #0\n", F ? 'f' : 's', 8 << size,
7087ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg);
7088ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
7089ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
7090ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 4: {
7091ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               /* VCLT #0 */
7092ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               IROp op;
7093ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               IRExpr *zero;
7094ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               if (Q) {
7095ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  zero = binop(Iop_64HLtoV128, mkU64(0), mkU64(0));
7096ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               } else {
7097ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  zero = mkU64(0);
7098ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               }
7099ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               if (F) {
7100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  switch (size) {
7101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     case 0: case 1: case 3: return False;
7102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     case 2: op = Q ? Iop_CmpGT32Fx4 : Iop_CmpGT32Fx2; break;
7103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     default: vassert(0);
7104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  }
7105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  assign(res, binop(op, zero, mkexpr(arg_m)));
7106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               } else {
7107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  switch (size) {
7108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     case 0: op = Q ? Iop_CmpGT8Sx16 : Iop_CmpGT8Sx8; break;
7109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     case 1: op = Q ? Iop_CmpGT16Sx8 : Iop_CmpGT16Sx4; break;
7110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     case 2: op = Q ? Iop_CmpGT32Sx4 : Iop_CmpGT32Sx2; break;
7111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     case 3: return False;
7112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     default: vassert(0);
7113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  }
7114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  assign(res, binop(op, zero, mkexpr(arg_m)));
7115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               }
7116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               DIP("vclt.%c%u %c%u, %c%u, #0\n", F ? 'f' : 's', 8 << size,
7117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg);
7118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
7119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
7120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 5:
7121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               return False;
7122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 6: {
7123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               /* VABS */
7124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               if (!F) {
7125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  IROp op;
7126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  switch(size) {
7127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     case 0: op = Q ? Iop_Abs8x16 : Iop_Abs8x8; break;
7128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     case 1: op = Q ? Iop_Abs16x8 : Iop_Abs16x4; break;
7129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     case 2: op = Q ? Iop_Abs32x4 : Iop_Abs32x2; break;
7130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     case 3: return False;
7131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     default: vassert(0);
7132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  }
7133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  assign(res, unop(op, mkexpr(arg_m)));
7134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               } else {
7135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  assign(res, unop(Q ? Iop_Abs32Fx4 : Iop_Abs32Fx2,
7136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                   mkexpr(arg_m)));
7137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               }
7138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               DIP("vabs.%c%u %c%u, %c%u\n",
7139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   F ? 'f' : 's', 8 << size, Q ? 'q' : 'd', dreg,
7140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   Q ? 'q' : 'd', mreg);
7141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
7142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
7143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 7: {
7144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               /* VNEG */
7145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               IROp op;
7146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               IRExpr *zero;
7147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               if (F) {
7148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  switch (size) {
7149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     case 0: case 1: case 3: return False;
7150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     case 2: op = Q ? Iop_Neg32Fx4 : Iop_Neg32Fx2; break;
7151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     default: vassert(0);
7152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  }
7153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  assign(res, unop(op, mkexpr(arg_m)));
7154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               } else {
7155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  if (Q) {
7156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     zero = binop(Iop_64HLtoV128, mkU64(0), mkU64(0));
7157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  } else {
7158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     zero = mkU64(0);
7159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  }
7160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  switch (size) {
7161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     case 0: op = Q ? Iop_Sub8x16 : Iop_Sub8x8; break;
7162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     case 1: op = Q ? Iop_Sub16x8 : Iop_Sub16x4; break;
7163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     case 2: op = Q ? Iop_Sub32x4 : Iop_Sub32x2; break;
7164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     case 3: return False;
7165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     default: vassert(0);
7166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  }
7167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  assign(res, binop(op, zero, mkexpr(arg_m)));
7168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               }
7169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               DIP("vneg.%c%u %c%u, %c%u\n",
7170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   F ? 'f' : 's', 8 << size, Q ? 'q' : 'd', dreg,
7171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   Q ? 'q' : 'd', mreg);
7172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
7173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
7174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            default:
7175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               vassert(0);
7176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
7177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (Q) {
7178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            putQReg(dreg, mkexpr(res), condT);
7179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
7180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            putDRegI64(dreg, mkexpr(res), condT);
7181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
7182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return True;
7183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 2:
7184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if ((B >> 1) == 0) {
7185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* VSWP */
7186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (Q) {
7187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               arg_m = newTemp(Ity_V128);
7188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               assign(arg_m, getQReg(mreg));
7189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               putQReg(mreg, getQReg(dreg), condT);
7190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               putQReg(dreg, mkexpr(arg_m), condT);
7191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else {
7192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               arg_m = newTemp(Ity_I64);
7193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               assign(arg_m, getDRegI64(mreg));
7194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               putDRegI64(mreg, getDRegI64(dreg), condT);
7195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               putDRegI64(dreg, mkexpr(arg_m), condT);
7196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
7197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            DIP("vswp %c%u, %c%u\n",
7198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg);
7199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return True;
7200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else if ((B >> 1) == 1) {
7201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* VTRN */
7202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            IROp op_lo, op_hi;
7203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            IRTemp res1, res2;
7204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (Q) {
7205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               arg_m = newTemp(Ity_V128);
7206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               arg_d = newTemp(Ity_V128);
7207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               res1 = newTemp(Ity_V128);
7208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               res2 = newTemp(Ity_V128);
7209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               assign(arg_m, getQReg(mreg));
7210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               assign(arg_d, getQReg(dreg));
7211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else {
7212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               res1 = newTemp(Ity_I64);
7213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               res2 = newTemp(Ity_I64);
7214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               arg_m = newTemp(Ity_I64);
7215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               arg_d = newTemp(Ity_I64);
7216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               assign(arg_m, getDRegI64(mreg));
7217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               assign(arg_d, getDRegI64(dreg));
7218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
7219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (Q) {
7220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               switch (size) {
7221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 0:
7222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op_lo = Iop_InterleaveOddLanes8x16;
7223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op_hi = Iop_InterleaveEvenLanes8x16;
7224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     break;
7225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 1:
7226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op_lo = Iop_InterleaveOddLanes16x8;
7227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op_hi = Iop_InterleaveEvenLanes16x8;
7228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     break;
7229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 2:
7230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op_lo = Iop_InterleaveOddLanes32x4;
7231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op_hi = Iop_InterleaveEvenLanes32x4;
7232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     break;
7233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 3:
7234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     return False;
7235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  default:
7236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     vassert(0);
7237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               }
7238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else {
7239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               switch (size) {
7240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 0:
7241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op_lo = Iop_InterleaveOddLanes8x8;
7242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op_hi = Iop_InterleaveEvenLanes8x8;
7243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     break;
7244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 1:
7245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op_lo = Iop_InterleaveOddLanes16x4;
7246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op_hi = Iop_InterleaveEvenLanes16x4;
7247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     break;
7248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 2:
7249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op_lo = Iop_InterleaveLO32x2;
7250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     op_hi = Iop_InterleaveHI32x2;
7251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     break;
7252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 3:
7253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     return False;
7254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  default:
7255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     vassert(0);
7256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               }
7257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
7258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            assign(res1, binop(op_lo, mkexpr(arg_m), mkexpr(arg_d)));
7259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            assign(res2, binop(op_hi, mkexpr(arg_m), mkexpr(arg_d)));
7260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (Q) {
7261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               putQReg(dreg, mkexpr(res1), condT);
7262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               putQReg(mreg, mkexpr(res2), condT);
7263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else {
7264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               putDRegI64(dreg, mkexpr(res1), condT);
7265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               putDRegI64(mreg, mkexpr(res2), condT);
7266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
7267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            DIP("vtrn.%u %c%u, %c%u\n",
7268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                8 << size, Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg);
7269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return True;
7270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else if ((B >> 1) == 2) {
7271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* VUZP */
7272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            IROp op_lo, op_hi;
7273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            IRTemp res1, res2;
7274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (!Q && size == 2)
7275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               return False;
7276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (Q) {
7277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               arg_m = newTemp(Ity_V128);
7278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               arg_d = newTemp(Ity_V128);
7279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               res1 = newTemp(Ity_V128);
7280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               res2 = newTemp(Ity_V128);
7281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               assign(arg_m, getQReg(mreg));
7282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               assign(arg_d, getQReg(dreg));
7283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else {
7284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               res1 = newTemp(Ity_I64);
7285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               res2 = newTemp(Ity_I64);
7286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               arg_m = newTemp(Ity_I64);
7287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               arg_d = newTemp(Ity_I64);
7288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               assign(arg_m, getDRegI64(mreg));
7289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               assign(arg_d, getDRegI64(dreg));
7290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
7291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            switch (size) {
7292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               case 0:
7293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  op_lo = Q ? Iop_CatOddLanes8x16 : Iop_CatOddLanes8x8;
7294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  op_hi = Q ? Iop_CatEvenLanes8x16 : Iop_CatEvenLanes8x8;
7295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  break;
7296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               case 1:
7297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  op_lo = Q ? Iop_CatOddLanes16x8 : Iop_CatOddLanes16x4;
7298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  op_hi = Q ? Iop_CatEvenLanes16x8 : Iop_CatEvenLanes16x4;
7299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  break;
7300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               case 2:
7301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  op_lo = Iop_CatOddLanes32x4;
7302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  op_hi = Iop_CatEvenLanes32x4;
7303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  break;
7304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               case 3:
7305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  return False;
7306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               default:
7307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  vassert(0);
7308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
7309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            assign(res1, binop(op_lo, mkexpr(arg_m), mkexpr(arg_d)));
7310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            assign(res2, binop(op_hi, mkexpr(arg_m), mkexpr(arg_d)));
7311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (Q) {
7312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               putQReg(dreg, mkexpr(res1), condT);
7313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               putQReg(mreg, mkexpr(res2), condT);
7314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else {
7315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               putDRegI64(dreg, mkexpr(res1), condT);
7316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               putDRegI64(mreg, mkexpr(res2), condT);
7317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
7318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            DIP("vuzp.%u %c%u, %c%u\n",
7319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                8 << size, Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg);
7320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return True;
7321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else if ((B >> 1) == 3) {
7322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* VZIP */
7323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            IROp op_lo, op_hi;
7324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            IRTemp res1, res2;
7325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (!Q && size == 2)
7326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               return False;
7327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (Q) {
7328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               arg_m = newTemp(Ity_V128);
7329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               arg_d = newTemp(Ity_V128);
7330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               res1 = newTemp(Ity_V128);
7331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               res2 = newTemp(Ity_V128);
7332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               assign(arg_m, getQReg(mreg));
7333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               assign(arg_d, getQReg(dreg));
7334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else {
7335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               res1 = newTemp(Ity_I64);
7336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               res2 = newTemp(Ity_I64);
7337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               arg_m = newTemp(Ity_I64);
7338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               arg_d = newTemp(Ity_I64);
7339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               assign(arg_m, getDRegI64(mreg));
7340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               assign(arg_d, getDRegI64(dreg));
7341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
7342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            switch (size) {
7343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               case 0:
7344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  op_lo = Q ? Iop_InterleaveHI8x16 : Iop_InterleaveHI8x8;
7345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  op_hi = Q ? Iop_InterleaveLO8x16 : Iop_InterleaveLO8x8;
7346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  break;
7347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               case 1:
7348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  op_lo = Q ? Iop_InterleaveHI16x8 : Iop_InterleaveHI16x4;
7349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  op_hi = Q ? Iop_InterleaveLO16x8 : Iop_InterleaveLO16x4;
7350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  break;
7351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               case 2:
7352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  op_lo = Iop_InterleaveHI32x4;
7353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  op_hi = Iop_InterleaveLO32x4;
7354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  break;
7355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               case 3:
7356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  return False;
7357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               default:
7358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  vassert(0);
7359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
7360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            assign(res1, binop(op_lo, mkexpr(arg_m), mkexpr(arg_d)));
7361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            assign(res2, binop(op_hi, mkexpr(arg_m), mkexpr(arg_d)));
7362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (Q) {
7363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               putQReg(dreg, mkexpr(res1), condT);
7364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               putQReg(mreg, mkexpr(res2), condT);
7365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else {
7366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               putDRegI64(dreg, mkexpr(res1), condT);
7367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               putDRegI64(mreg, mkexpr(res2), condT);
7368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
7369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            DIP("vzip.%u %c%u, %c%u\n",
7370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                8 << size, Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg);
7371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return True;
7372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else if (B == 8) {
7373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* VMOVN */
7374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            IROp op;
7375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            mreg >>= 1;
7376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            switch (size) {
7377b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               case 0: op = Iop_NarrowUn16to8x8;  break;
7378b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               case 1: op = Iop_NarrowUn32to16x4; break;
7379b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               case 2: op = Iop_NarrowUn64to32x2; break;
7380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               case 3: return False;
7381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               default: vassert(0);
7382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
7383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            putDRegI64(dreg, unop(op, getQReg(mreg)), condT);
7384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            DIP("vmovn.i%u d%u, q%u\n", 16 << size, dreg, mreg);
7385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return True;
7386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else if (B == 9 || (B >> 1) == 5) {
7387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* VQMOVN, VQMOVUN */
7388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            IROp op, op2;
7389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            IRTemp tmp;
7390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            dreg = ((theInstr >> 18) & 0x10) | ((theInstr >> 12) & 0xF);
7391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            mreg = ((theInstr >> 1) & 0x10) | (theInstr & 0xF);
7392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (mreg & 1)
7393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               return False;
7394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            mreg >>= 1;
7395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            switch (size) {
7396b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               case 0: op2 = Iop_NarrowUn16to8x8;  break;
7397b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               case 1: op2 = Iop_NarrowUn32to16x4; break;
7398b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               case 2: op2 = Iop_NarrowUn64to32x2; break;
7399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               case 3: return False;
7400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               default: vassert(0);
7401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
7402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            switch (B & 3) {
7403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               case 0:
7404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  vassert(0);
7405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               case 1:
7406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  switch (size) {
7407b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                     case 0: op = Iop_QNarrowUn16Sto8Ux8;  break;
7408b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                     case 1: op = Iop_QNarrowUn32Sto16Ux4; break;
7409b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                     case 2: op = Iop_QNarrowUn64Sto32Ux2; break;
7410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     case 3: return False;
7411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     default: vassert(0);
7412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  }
7413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  DIP("vqmovun.s%u d%u, q%u\n", 16 << size, dreg, mreg);
7414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  break;
7415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               case 2:
7416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  switch (size) {
7417b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                     case 0: op = Iop_QNarrowUn16Sto8Sx8;  break;
7418b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                     case 1: op = Iop_QNarrowUn32Sto16Sx4; break;
7419b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                     case 2: op = Iop_QNarrowUn64Sto32Sx2; break;
7420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     case 3: return False;
7421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     default: vassert(0);
7422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  }
7423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  DIP("vqmovn.s%u d%u, q%u\n", 16 << size, dreg, mreg);
7424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  break;
7425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               case 3:
7426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  switch (size) {
7427b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                     case 0: op = Iop_QNarrowUn16Uto8Ux8;  break;
7428b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                     case 1: op = Iop_QNarrowUn32Uto16Ux4; break;
7429b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                     case 2: op = Iop_QNarrowUn64Uto32Ux2; break;
7430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     case 3: return False;
7431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     default: vassert(0);
7432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  }
7433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  DIP("vqmovn.u%u d%u, q%u\n", 16 << size, dreg, mreg);
7434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  break;
7435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               default:
7436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  vassert(0);
7437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
7438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            res = newTemp(Ity_I64);
7439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            tmp = newTemp(Ity_I64);
7440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            assign(res, unop(op, getQReg(mreg)));
7441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#ifndef DISABLE_QC_FLAG
7442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            assign(tmp, unop(op2, getQReg(mreg)));
7443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            setFlag_QC(mkexpr(res), mkexpr(tmp), False, condT);
7444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
7445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            putDRegI64(dreg, mkexpr(res), condT);
7446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return True;
7447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else if (B == 12) {
7448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* VSHLL (maximum shift) */
7449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            IROp op, cvt;
7450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            UInt shift_imm;
7451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (Q)
7452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               return False;
7453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (dreg & 1)
7454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               return False;
7455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            dreg >>= 1;
7456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            shift_imm = 8 << size;
7457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            res = newTemp(Ity_V128);
7458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            switch (size) {
7459b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               case 0: op = Iop_ShlN16x8; cvt = Iop_Widen8Uto16x8;  break;
7460b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               case 1: op = Iop_ShlN32x4; cvt = Iop_Widen16Uto32x4; break;
7461b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               case 2: op = Iop_ShlN64x2; cvt = Iop_Widen32Uto64x2; break;
7462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               case 3: return False;
7463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               default: vassert(0);
7464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
7465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            assign(res, binop(op, unop(cvt, getDRegI64(mreg)),
7466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                  mkU8(shift_imm)));
7467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            putQReg(dreg, mkexpr(res), condT);
7468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            DIP("vshll.i%u q%u, d%u, #%u\n", 8 << size, dreg, mreg, 8 << size);
7469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return True;
7470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else if ((B >> 3) == 3 && (B & 3) == 0) {
7471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* VCVT (half<->single) */
7472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* Half-precision extensions are needed to run this */
7473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vassert(0); // ATC
7474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (((theInstr >> 18) & 3) != 1)
7475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               return False;
7476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if ((theInstr >> 8) & 1) {
7477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               if (dreg & 1)
7478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  return False;
7479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               dreg >>= 1;
7480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               putQReg(dreg, unop(Iop_F16toF32x4, getDRegI64(mreg)),
7481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     condT);
7482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               DIP("vcvt.f32.f16 q%u, d%u\n", dreg, mreg);
7483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else {
7484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               if (mreg & 1)
7485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  return False;
7486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               mreg >>= 1;
7487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               putDRegI64(dreg, unop(Iop_F32toF16x4, getQReg(mreg)),
7488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                condT);
7489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               DIP("vcvt.f16.f32 d%u, q%u\n", dreg, mreg);
7490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
7491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return True;
7492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
7493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return False;
7494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
7495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(0);
7496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return True;
7497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 3:
7498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (((B >> 1) & BITS4(1,1,0,1)) == BITS4(1,0,0,0)) {
7499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* VRECPE */
7500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            IROp op;
7501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            F = (theInstr >> 8) & 1;
7502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (size != 2)
7503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               return False;
7504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (Q) {
7505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               op = F ? Iop_Recip32Fx4 : Iop_Recip32x4;
7506ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               putQReg(dreg, unop(op, getQReg(mreg)), condT);
7507ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               DIP("vrecpe.%c32 q%u, q%u\n", F ? 'f' : 'u', dreg, mreg);
7508ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else {
7509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               op = F ? Iop_Recip32Fx2 : Iop_Recip32x2;
7510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               putDRegI64(dreg, unop(op, getDRegI64(mreg)), condT);
7511ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               DIP("vrecpe.%c32 d%u, d%u\n", F ? 'f' : 'u', dreg, mreg);
7512ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
7513ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return True;
7514ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else if (((B >> 1) & BITS4(1,1,0,1)) == BITS4(1,0,0,1)) {
7515ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* VRSQRTE */
7516ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            IROp op;
7517ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            F = (B >> 2) & 1;
7518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (size != 2)
7519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               return False;
7520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (F) {
7521ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               /* fp */
7522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               op = Q ? Iop_Rsqrte32Fx4 : Iop_Rsqrte32Fx2;
7523ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else {
7524ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               /* unsigned int */
7525ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               op = Q ? Iop_Rsqrte32x4 : Iop_Rsqrte32x2;
7526ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
7527ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (Q) {
7528ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               putQReg(dreg, unop(op, getQReg(mreg)), condT);
7529ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               DIP("vrsqrte.%c32 q%u, q%u\n", F ? 'f' : 'u', dreg, mreg);
7530ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else {
7531ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               putDRegI64(dreg, unop(op, getDRegI64(mreg)), condT);
7532ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               DIP("vrsqrte.%c32 d%u, d%u\n", F ? 'f' : 'u', dreg, mreg);
7533ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
7534ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return True;
7535ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else if ((B >> 3) == 3) {
7536ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* VCVT (fp<->integer) */
7537ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            IROp op;
7538ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (size != 2)
7539ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               return False;
7540ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            switch ((B >> 1) & 3) {
7541ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               case 0:
7542ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  op = Q ? Iop_I32StoFx4 : Iop_I32StoFx2;
7543ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  DIP("vcvt.f32.s32 %c%u, %c%u\n",
7544ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg);
7545ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  break;
7546ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               case 1:
7547ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  op = Q ? Iop_I32UtoFx4 : Iop_I32UtoFx2;
7548ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  DIP("vcvt.f32.u32 %c%u, %c%u\n",
7549ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg);
7550ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  break;
7551ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               case 2:
7552ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  op = Q ? Iop_FtoI32Sx4_RZ : Iop_FtoI32Sx2_RZ;
7553ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  DIP("vcvt.s32.f32 %c%u, %c%u\n",
7554ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg);
7555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  break;
7556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               case 3:
7557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  op = Q ? Iop_FtoI32Ux4_RZ : Iop_FtoI32Ux2_RZ;
7558ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  DIP("vcvt.u32.f32 %c%u, %c%u\n",
7559ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg);
7560ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  break;
7561ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               default:
7562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  vassert(0);
7563ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
7564ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (Q) {
7565ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               putQReg(dreg, unop(op, getQReg(mreg)), condT);
7566ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else {
7567ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               putDRegI64(dreg, unop(op, getDRegI64(mreg)), condT);
7568ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
7569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return True;
7570ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
7571ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return False;
7572ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
7573ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(0);
7574ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return True;
7575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
7576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(0);
7577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
7578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return False;
7579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
7580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7581ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* A7.4.6 One register and a modified immediate value */
7582ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
7583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid ppNeonImm(UInt imm, UInt cmode, UInt op)
7584ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
7585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   int i;
7586ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (cmode) {
7587ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0: case 1: case 8: case 9:
7588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("0x%x", imm);
7589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
7590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 2: case 3: case 10: case 11:
7591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("0x%x00", imm);
7592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
7593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 4: case 5:
7594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("0x%x0000", imm);
7595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
7596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 6: case 7:
7597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("0x%x000000", imm);
7598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
7599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 12:
7600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("0x%xff", imm);
7601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
7602ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 13:
7603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("0x%xffff", imm);
7604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
7605ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 14:
7606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (op) {
7607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vex_printf("0x");
7608ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            for (i = 7; i >= 0; i--)
7609ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               vex_printf("%s", (imm & (1 << i)) ? "ff" : "00");
7610ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
7611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vex_printf("0x%x", imm);
7612ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
7613ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
7614ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 15:
7615ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("0x%x", imm);
7616ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
7617ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
7618ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
7619ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7620ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
7621ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownconst char *ppNeonImmType(UInt cmode, UInt op)
7622ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
7623ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (cmode) {
7624ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0 ... 7:
7625ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 12: case 13:
7626ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return "i32";
7627ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 8 ... 11:
7628ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return "i16";
7629ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 14:
7630ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (op)
7631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return "i64";
7632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         else
7633ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return "i8";
7634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 15:
7635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (op)
7636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vassert(0);
7637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         else
7638ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return "f32";
7639ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
7640ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(0);
7641ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
7642ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
7643ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7644ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
7645ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid DIPimm(UInt imm, UInt cmode, UInt op,
7646ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            const char *instr, UInt Q, UInt dreg)
7647ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
7648ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (vex_traceflags & VEX_TRACE_FE) {
7649ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vex_printf("%s.%s %c%u, #", instr,
7650ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 ppNeonImmType(cmode, op), Q ? 'q' : 'd', dreg);
7651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ppNeonImm(imm, cmode, op);
7652ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vex_printf("\n");
7653ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
7654ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
7655ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7656ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
7657ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownBool dis_neon_data_1reg_and_imm ( UInt theInstr, IRTemp condT )
7658ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
7659ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt dreg = get_neon_d_regno(theInstr);
7660ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ULong imm_raw = ((theInstr >> 17) & 0x80) | ((theInstr >> 12) & 0x70) |
7661ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  (theInstr & 0xf);
7662ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ULong imm_raw_pp = imm_raw;
7663ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt cmode = (theInstr >> 8) & 0xf;
7664ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt op_bit = (theInstr >> 5) & 1;
7665ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ULong imm = 0;
7666ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt Q = (theInstr >> 6) & 1;
7667ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   int i, j;
7668ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt tmp;
7669ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRExpr *imm_val;
7670ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRExpr *expr;
7671ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp tmp_var;
7672ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch(cmode) {
7673ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 7: case 6:
7674ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         imm_raw = imm_raw << 8;
7675ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* fallthrough */
7676ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 5: case 4:
7677ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         imm_raw = imm_raw << 8;
7678ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* fallthrough */
7679ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 3: case 2:
7680ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         imm_raw = imm_raw << 8;
7681ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* fallthrough */
7682ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0: case 1:
7683ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         imm = (imm_raw << 32) | imm_raw;
7684ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
7685ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 11: case 10:
7686ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         imm_raw = imm_raw << 8;
7687ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* fallthrough */
7688ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 9: case 8:
7689ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         imm_raw = (imm_raw << 16) | imm_raw;
7690ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         imm = (imm_raw << 32) | imm_raw;
7691ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
7692ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 13:
7693ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         imm_raw = (imm_raw << 8) | 0xff;
7694ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* fallthrough */
7695ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 12:
7696ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         imm_raw = (imm_raw << 8) | 0xff;
7697ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         imm = (imm_raw << 32) | imm_raw;
7698ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
7699ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 14:
7700ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (! op_bit) {
7701ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            for(i = 0; i < 8; i++) {
7702ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               imm = (imm << 8) | imm_raw;
7703ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
7704ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
7705ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            for(i = 7; i >= 0; i--) {
7706ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               tmp = 0;
7707ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               for(j = 0; j < 8; j++) {
7708ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  tmp = (tmp << 1) | ((imm_raw >> i) & 1);
7709ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               }
7710ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               imm = (imm << 8) | tmp;
7711ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
7712ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
7713ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
7714ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 15:
7715ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         imm = (imm_raw & 0x80) << 5;
7716b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         imm |= ((~imm_raw & 0x40) << 5);
7717ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         for(i = 1; i <= 4; i++)
7718ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            imm |= (imm_raw & 0x40) << i;
7719ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         imm |= (imm_raw & 0x7f);
7720ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         imm = imm << 19;
7721ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         imm = (imm << 32) | imm;
7722ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
7723ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
7724ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return False;
7725ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
7726ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (Q) {
7727ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      imm_val = binop(Iop_64HLtoV128, mkU64(imm), mkU64(imm));
7728ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
7729ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      imm_val = mkU64(imm);
7730ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
7731ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (((op_bit == 0) &&
7732ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      (((cmode & 9) == 0) || ((cmode & 13) == 8) || ((cmode & 12) == 12))) ||
7733ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ((op_bit == 1) && (cmode == 14))) {
7734ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* VMOV (immediate) */
7735ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (Q) {
7736ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putQReg(dreg, imm_val, condT);
7737ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else {
7738ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putDRegI64(dreg, imm_val, condT);
7739ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
7740ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIPimm(imm_raw_pp, cmode, op_bit, "vmov", Q, dreg);
7741ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return True;
7742ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
7743ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if ((op_bit == 1) &&
7744ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      (((cmode & 9) == 0) || ((cmode & 13) == 8) || ((cmode & 14) == 12))) {
7745ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* VMVN (immediate) */
7746ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (Q) {
7747ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putQReg(dreg, unop(Iop_NotV128, imm_val), condT);
7748ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else {
7749ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putDRegI64(dreg, unop(Iop_Not64, imm_val), condT);
7750ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
7751ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIPimm(imm_raw_pp, cmode, op_bit, "vmvn", Q, dreg);
7752ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return True;
7753ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
7754ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (Q) {
7755ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      tmp_var = newTemp(Ity_V128);
7756ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign(tmp_var, getQReg(dreg));
7757ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
7758ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      tmp_var = newTemp(Ity_I64);
7759ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign(tmp_var, getDRegI64(dreg));
7760ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
7761ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if ((op_bit == 0) && (((cmode & 9) == 1) || ((cmode & 13) == 9))) {
7762ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* VORR (immediate) */
7763ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (Q)
7764ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         expr = binop(Iop_OrV128, mkexpr(tmp_var), imm_val);
7765ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      else
7766ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         expr = binop(Iop_Or64, mkexpr(tmp_var), imm_val);
7767ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIPimm(imm_raw_pp, cmode, op_bit, "vorr", Q, dreg);
7768ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else if ((op_bit == 1) && (((cmode & 9) == 1) || ((cmode & 13) == 9))) {
7769ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* VBIC (immediate) */
7770ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (Q)
7771ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         expr = binop(Iop_AndV128, mkexpr(tmp_var),
7772ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                   unop(Iop_NotV128, imm_val));
7773ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      else
7774ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         expr = binop(Iop_And64, mkexpr(tmp_var), unop(Iop_Not64, imm_val));
7775ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIPimm(imm_raw_pp, cmode, op_bit, "vbic", Q, dreg);
7776ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
7777ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return False;
7778ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
7779ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (Q)
7780ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putQReg(dreg, expr, condT);
7781ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   else
7782ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putDRegI64(dreg, expr, condT);
7783ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return True;
7784ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
7785ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7786ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* A7.4 Advanced SIMD data-processing instructions */
7787ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
7788ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownBool dis_neon_data_processing ( UInt theInstr, IRTemp condT )
7789ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
7790ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt A = (theInstr >> 19) & 0x1F;
7791ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt B = (theInstr >>  8) & 0xF;
7792ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt C = (theInstr >>  4) & 0xF;
7793ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt U = (theInstr >> 24) & 0x1;
7794ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7795ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (! (A & 0x10)) {
7796ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return dis_neon_data_3same(theInstr, condT);
7797ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
7798ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (((A & 0x17) == 0x10) && ((C & 0x9) == 0x1)) {
7799ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return dis_neon_data_1reg_and_imm(theInstr, condT);
7800ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
7801ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if ((C & 1) == 1) {
7802ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return dis_neon_data_2reg_and_shift(theInstr, condT);
7803ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
7804ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (((C & 5) == 0) && (((A & 0x14) == 0x10) || ((A & 0x16) == 0x14))) {
7805ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return dis_neon_data_3diff(theInstr, condT);
7806ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
7807ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (((C & 5) == 4) && (((A & 0x14) == 0x10) || ((A & 0x16) == 0x14))) {
7808ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return dis_neon_data_2reg_and_scalar(theInstr, condT);
7809ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
7810ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if ((A & 0x16) == 0x16) {
7811ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if ((U == 0) && ((C & 1) == 0)) {
7812ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return dis_neon_vext(theInstr, condT);
7813ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
7814ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if ((U != 1) || ((C & 1) == 1))
7815ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return False;
7816ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if ((B & 8) == 0) {
7817ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return dis_neon_data_2reg_misc(theInstr, condT);
7818ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
7819ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if ((B & 12) == 8) {
7820ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return dis_neon_vtb(theInstr, condT);
7821ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
7822ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if ((B == 12) && ((C & 9) == 0)) {
7823ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return dis_neon_vdup(theInstr, condT);
7824ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
7825ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
7826ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return False;
7827ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
7828ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7829ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7830ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
7831ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- NEON loads and stores                                ---*/
7832ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
7833ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7834ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* For NEON memory operations, we use the standard scheme to handle
7835ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   conditionalisation: generate a jump around the instruction if the
7836ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   condition is false.  That's only necessary in Thumb mode, however,
7837ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   since in ARM mode NEON instructions are unconditional. */
7838ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7839ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* A helper function for what follows.  It assumes we already went
7840ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   uncond as per comments at the top of this section. */
7841ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
7842ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid mk_neon_elem_load_to_one_lane( UInt rD, UInt inc, UInt index,
7843ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                    UInt N, UInt size, IRTemp addr )
7844ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
7845ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt i;
7846ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (size) {
7847ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0:
7848ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putDRegI64(rD, triop(Iop_SetElem8x8, getDRegI64(rD), mkU8(index),
7849ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    loadLE(Ity_I8, mkexpr(addr))), IRTemp_INVALID);
7850ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
7851ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 1:
7852ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putDRegI64(rD, triop(Iop_SetElem16x4, getDRegI64(rD), mkU8(index),
7853ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    loadLE(Ity_I16, mkexpr(addr))), IRTemp_INVALID);
7854ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
7855ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 2:
7856ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putDRegI64(rD, triop(Iop_SetElem32x2, getDRegI64(rD), mkU8(index),
7857ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    loadLE(Ity_I32, mkexpr(addr))), IRTemp_INVALID);
7858ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
7859ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
7860ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(0);
7861ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
7862ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (i = 1; i <= N; i++) {
7863ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch (size) {
7864ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case 0:
7865ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            putDRegI64(rD + i * inc,
7866ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       triop(Iop_SetElem8x8,
7867ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             getDRegI64(rD + i * inc),
7868ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             mkU8(index),
7869ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             loadLE(Ity_I8, binop(Iop_Add32,
7870ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                                  mkexpr(addr),
7871ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                                  mkU32(i * 1)))),
7872ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       IRTemp_INVALID);
7873ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
7874ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case 1:
7875ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            putDRegI64(rD + i * inc,
7876ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       triop(Iop_SetElem16x4,
7877ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             getDRegI64(rD + i * inc),
7878ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             mkU8(index),
7879ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             loadLE(Ity_I16, binop(Iop_Add32,
7880ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                                   mkexpr(addr),
7881ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                                   mkU32(i * 2)))),
7882ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       IRTemp_INVALID);
7883ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
7884ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case 2:
7885ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            putDRegI64(rD + i * inc,
7886ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       triop(Iop_SetElem32x2,
7887ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             getDRegI64(rD + i * inc),
7888ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             mkU8(index),
7889ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             loadLE(Ity_I32, binop(Iop_Add32,
7890ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                                   mkexpr(addr),
7891ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                                   mkU32(i * 4)))),
7892ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       IRTemp_INVALID);
7893ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
7894ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         default:
7895ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vassert(0);
7896ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
7897ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
7898ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
7899ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7900ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* A(nother) helper function for what follows.  It assumes we already
7901ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   went uncond as per comments at the top of this section. */
7902ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
7903ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid mk_neon_elem_store_from_one_lane( UInt rD, UInt inc, UInt index,
7904ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                       UInt N, UInt size, IRTemp addr )
7905ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
7906ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt i;
7907ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (size) {
7908ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0:
7909ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         storeLE(mkexpr(addr),
7910ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 binop(Iop_GetElem8x8, getDRegI64(rD), mkU8(index)));
7911ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
7912ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 1:
7913ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         storeLE(mkexpr(addr),
7914ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 binop(Iop_GetElem16x4, getDRegI64(rD), mkU8(index)));
7915ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
7916ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 2:
7917ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         storeLE(mkexpr(addr),
7918ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 binop(Iop_GetElem32x2, getDRegI64(rD), mkU8(index)));
7919ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
7920ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
7921ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(0);
7922ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
7923ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (i = 1; i <= N; i++) {
7924ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch (size) {
7925ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case 0:
7926ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            storeLE(binop(Iop_Add32, mkexpr(addr), mkU32(i * 1)),
7927ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    binop(Iop_GetElem8x8, getDRegI64(rD + i * inc),
7928ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                          mkU8(index)));
7929ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
7930ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case 1:
7931ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            storeLE(binop(Iop_Add32, mkexpr(addr), mkU32(i * 2)),
7932ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    binop(Iop_GetElem16x4, getDRegI64(rD + i * inc),
7933ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                           mkU8(index)));
7934ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
7935ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case 2:
7936ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            storeLE(binop(Iop_Add32, mkexpr(addr), mkU32(i * 4)),
7937ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    binop(Iop_GetElem32x2, getDRegI64(rD + i * inc),
7938ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                           mkU8(index)));
7939ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
7940ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         default:
7941ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vassert(0);
7942ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
7943ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
7944ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
7945ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7946ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* A7.7 Advanced SIMD element or structure load/store instructions */
7947ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
7948b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy StepanovBool dis_neon_load_or_store ( UInt theInstr,
7949b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                              Bool isT, IRTemp condT )
7950ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
7951ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  define INSN(_bMax,_bMin)  SLICE_UInt(theInstr, (_bMax), (_bMin))
7952b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   UInt bA = INSN(23,23);
7953b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   UInt fB = INSN(11,8);
7954b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   UInt bL = INSN(21,21);
7955ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt rD = (INSN(22,22) << 4) | INSN(15,12);
7956ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt rN = INSN(19,16);
7957ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt rM = INSN(3,0);
7958ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt N, size, i, j;
7959ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt inc;
7960ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt regs = 1;
7961ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7962ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (isT) {
7963ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert(condT != IRTemp_INVALID);
7964ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
7965ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert(condT == IRTemp_INVALID);
7966ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
7967ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* So now, if condT is not IRTemp_INVALID, we know we're
7968ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      dealing with Thumb code. */
7969ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7970ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (INSN(20,20) != 0)
7971ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return False;
7972ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7973ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp initialRn = newTemp(Ity_I32);
7974ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign(initialRn, isT ? getIRegT(rN) : getIRegA(rN));
7975ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7976ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp initialRm = newTemp(Ity_I32);
7977ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign(initialRm, isT ? getIRegT(rM) : getIRegA(rM));
7978ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7979b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   /* There are 3 cases:
7980b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      (1) VSTn / VLDn (n-element structure from/to one lane)
7981b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      (2) VLDn (single element to all lanes)
7982b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      (3) VSTn / VLDn (multiple n-element structures)
7983b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   */
7984b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   if (bA) {
7985b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      N = fB & 3;
7986b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      if ((fB >> 2) < 3) {
7987b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         /* ------------ Case (1) ------------
7988b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            VSTn / VLDn (n-element structure from/to one lane) */
7989ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7990b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         size = fB >> 2;
7991ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7992ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         switch (size) {
7993ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 0: i = INSN(7,5); inc = 1; break;
7994ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 1: i = INSN(7,6); inc = INSN(5,5) ? 2 : 1; break;
7995ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 2: i = INSN(7,7); inc = INSN(6,6) ? 2 : 1; break;
7996ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 3: return False;
7997ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            default: vassert(0);
7998ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
7999ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8000ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp addr = newTemp(Ity_I32);
8001ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign(addr, mkexpr(initialRn));
8002ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8003ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         // go uncond
8004ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (condT != IRTemp_INVALID)
8005ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            mk_skip_over_T32_if_cond_is_false(condT);
8006ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         // now uncond
8007ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8008b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         if (bL)
8009ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            mk_neon_elem_load_to_one_lane(rD, inc, i, N, size, addr);
8010ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         else
8011ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            mk_neon_elem_store_from_one_lane(rD, inc, i, N, size, addr);
8012b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         DIP("v%s%u.%u {", bL ? "ld" : "st", N + 1, 8 << size);
8013ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         for (j = 0; j <= N; j++) {
8014ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (j)
8015ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               DIP(", ");
8016ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            DIP("d%u[%u]", rD + j * inc, i);
8017ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
8018ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("}, [r%u]", rN);
8019ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (rM != 13 && rM != 15) {
8020ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            DIP(", r%u\n", rM);
8021ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
8022ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            DIP("%s\n", (rM != 15) ? "!" : "");
8023ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
8024ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else {
8025b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         /* ------------ Case (2) ------------
8026b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            VLDn (single element to all lanes) */
8027ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         UInt r;
8028b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         if (bL == 0)
8029ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return False;
8030ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8031ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         inc = INSN(5,5) + 1;
8032ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         size = INSN(7,6);
8033ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8034ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* size == 3 and size == 2 cases differ in alignment constraints */
8035ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (size == 3 && N == 3 && INSN(4,4) == 1)
8036ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            size = 2;
8037ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8038ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (size == 0 && N == 0 && INSN(4,4) == 1)
8039ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return False;
8040ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (N == 2 && INSN(4,4) == 1)
8041ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return False;
8042ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (size == 3)
8043ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return False;
8044ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8045ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         // go uncond
8046ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (condT != IRTemp_INVALID)
8047ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            mk_skip_over_T32_if_cond_is_false(condT);
8048ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         // now uncond
8049ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8050ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp addr = newTemp(Ity_I32);
8051ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign(addr, mkexpr(initialRn));
8052ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8053ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (N == 0 && INSN(5,5))
8054ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            regs = 2;
8055ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8056ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         for (r = 0; r < regs; r++) {
8057ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            switch (size) {
8058ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               case 0:
8059ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  putDRegI64(rD + r, unop(Iop_Dup8x8,
8060ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                          loadLE(Ity_I8, mkexpr(addr))),
8061ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             IRTemp_INVALID);
8062ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  break;
8063ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               case 1:
8064ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  putDRegI64(rD + r, unop(Iop_Dup16x4,
8065ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                          loadLE(Ity_I16, mkexpr(addr))),
8066ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             IRTemp_INVALID);
8067ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  break;
8068ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               case 2:
8069ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  putDRegI64(rD + r, unop(Iop_Dup32x2,
8070ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                          loadLE(Ity_I32, mkexpr(addr))),
8071ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             IRTemp_INVALID);
8072ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  break;
8073ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               default:
8074ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  vassert(0);
8075ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
8076ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            for (i = 1; i <= N; i++) {
8077ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               switch (size) {
8078ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 0:
8079ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     putDRegI64(rD + r + i * inc,
8080ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                unop(Iop_Dup8x8,
8081ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                     loadLE(Ity_I8, binop(Iop_Add32,
8082ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                                          mkexpr(addr),
8083ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                                          mkU32(i * 1)))),
8084ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                IRTemp_INVALID);
8085ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     break;
8086ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 1:
8087ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     putDRegI64(rD + r + i * inc,
8088ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                unop(Iop_Dup16x4,
8089ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                     loadLE(Ity_I16, binop(Iop_Add32,
8090ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                                           mkexpr(addr),
8091ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                                           mkU32(i * 2)))),
8092ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                IRTemp_INVALID);
8093ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     break;
8094ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case 2:
8095ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     putDRegI64(rD + r + i * inc,
8096ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                unop(Iop_Dup32x2,
8097ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                     loadLE(Ity_I32, binop(Iop_Add32,
8098ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                                           mkexpr(addr),
8099ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                                           mkU32(i * 4)))),
8100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                IRTemp_INVALID);
8101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     break;
8102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  default:
8103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     vassert(0);
8104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               }
8105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
8106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
8107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("vld%u.%u {", N + 1, 8 << size);
8108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         for (r = 0; r < regs; r++) {
8109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            for (i = 0; i <= N; i++) {
8110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               if (i || r)
8111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  DIP(", ");
8112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               DIP("d%u[]", rD + r + i * inc);
8113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
8114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
8115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("}, [r%u]", rN);
8116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (rM != 13 && rM != 15) {
8117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            DIP(", r%u\n", rM);
8118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
8119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            DIP("%s\n", (rM != 15) ? "!" : "");
8120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
8121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
8122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Writeback.  We're uncond here, so no condT-ing. */
8123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (rM != 15) {
8124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (rM == 13) {
8125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            IRExpr* e = binop(Iop_Add32,
8126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              mkexpr(initialRn),
8127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              mkU32((1 << size) * (N + 1)));
8128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (isT)
8129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               putIRegT(rN, e, IRTemp_INVALID);
8130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            else
8131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               putIRegA(rN, e, IRTemp_INVALID, Ijk_Boring);
8132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
8133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            IRExpr* e = binop(Iop_Add32,
8134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              mkexpr(initialRn),
8135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              mkexpr(initialRm));
8136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (isT)
8137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               putIRegT(rN, e, IRTemp_INVALID);
8138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            else
8139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               putIRegA(rN, e, IRTemp_INVALID, Ijk_Boring);
8140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
8141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
8142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return True;
8143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
8144b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      /* ------------ Case (3) ------------
8145b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         VSTn / VLDn (multiple n-element structures) */
8146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp tmp;
8147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt r, elems;
8148b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      if (fB == BITS4(0,0,1,0) || fB == BITS4(0,1,1,0)
8149b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov          || fB == BITS4(0,1,1,1) || fB == BITS4(1,0,1,0)) {
8150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         N = 0;
8151b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      } else if (fB == BITS4(0,0,1,1) || fB == BITS4(1,0,0,0)
8152b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                 || fB == BITS4(1,0,0,1)) {
8153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         N = 1;
8154b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      } else if (fB == BITS4(0,1,0,0) || fB == BITS4(0,1,0,1)) {
8155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         N = 2;
8156b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      } else if (fB == BITS4(0,0,0,0) || fB == BITS4(0,0,0,1)) {
8157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         N = 3;
8158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else {
8159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return False;
8160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
8161b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      inc = (fB & 1) + 1;
8162b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      if (N == 1 && fB == BITS4(0,0,1,1)) {
8163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         regs = 2;
8164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else if (N == 0) {
8165b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         if (fB == BITS4(1,0,1,0)) {
8166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            regs = 2;
8167b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         } else if (fB == BITS4(0,1,1,0)) {
8168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            regs = 3;
8169b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         } else if (fB == BITS4(0,0,1,0)) {
8170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            regs = 4;
8171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
8172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
8173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      size = INSN(7,6);
8175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (N == 0 && size == 3)
8176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         size = 2;
8177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (size == 3)
8178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return False;
8179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      elems = 8 / (1 << size);
8181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // go uncond
8183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (condT != IRTemp_INVALID)
8184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         mk_skip_over_T32_if_cond_is_false(condT);
8185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // now uncond
8186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp addr = newTemp(Ity_I32);
8188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign(addr, mkexpr(initialRn));
8189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      for (r = 0; r < regs; r++) {
8191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         for (i = 0; i < elems; i++) {
8192b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            if (bL)
8193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               mk_neon_elem_load_to_one_lane(rD + r, inc, i, N, size, addr);
8194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            else
8195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               mk_neon_elem_store_from_one_lane(rD + r, inc, i, N, size, addr);
8196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            tmp = newTemp(Ity_I32);
8197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            assign(tmp, binop(Iop_Add32, mkexpr(addr),
8198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                         mkU32((1 << size) * (N + 1))));
8199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addr = tmp;
8200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
8201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
8202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Writeback */
8203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (rM != 15) {
8204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (rM == 13) {
8205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            IRExpr* e = binop(Iop_Add32,
8206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              mkexpr(initialRn),
8207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              mkU32(8 * (N + 1) * regs));
8208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (isT)
8209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               putIRegT(rN, e, IRTemp_INVALID);
8210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            else
8211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               putIRegA(rN, e, IRTemp_INVALID, Ijk_Boring);
8212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
8213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            IRExpr* e = binop(Iop_Add32,
8214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              mkexpr(initialRn),
8215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              mkexpr(initialRm));
8216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (isT)
8217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               putIRegT(rN, e, IRTemp_INVALID);
8218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            else
8219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               putIRegA(rN, e, IRTemp_INVALID, Ijk_Boring);
8220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
8221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
8222b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      DIP("v%s%u.%u {", bL ? "ld" : "st", N + 1, 8 << INSN(7,6));
8223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if ((inc == 1 && regs * (N + 1) > 1)
8224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          || (inc == 2 && regs > 1 && N > 0)) {
8225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("d%u-d%u", rD, rD + regs * (N + 1) - 1);
8226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else {
8227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         for (r = 0; r < regs; r++) {
8228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            for (i = 0; i <= N; i++) {
8229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               if (i || r)
8230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  DIP(", ");
8231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               DIP("d%u", rD + r + i * inc);
8232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
8233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
8234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
8235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("}, [r%u]", rN);
8236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (rM != 13 && rM != 15) {
8237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP(", r%u\n", rM);
8238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else {
8239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("%s\n", (rM != 15) ? "!" : "");
8240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
8241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return True;
8242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
8243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  undef INSN
8244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
8245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
8248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- NEON, top level control                              ---*/
8249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
8250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Both ARM and Thumb */
8252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Translate a NEON instruction.    If successful, returns
8254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   True and *dres may or may not be updated.  If failure, returns
8255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   False and doesn't change *dres nor create any IR.
8256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   The Thumb and ARM encodings are similar for the 24 bottom bits, but
8258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   the top 8 bits are slightly different.  In both cases, the caller
8259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   must pass the entire 32 bits.  Callers may pass any instruction;
8260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   this ignores non-NEON ones.
8261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Caller must supply an IRTemp 'condT' holding the gating condition,
8263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   or IRTemp_INVALID indicating the insn is always executed.  In ARM
8264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   code, this must always be IRTemp_INVALID because NEON insns are
8265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   unconditional for ARM.
8266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Finally, the caller must indicate whether this occurs in ARM or in
8268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Thumb code.
8269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
8270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool decode_NEON_instruction (
8271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               /*MOD*/DisResult* dres,
8272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               UInt              insn32,
8273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               IRTemp            condT,
8274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               Bool              isT
8275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            )
8276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
8277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  define INSN(_bMax,_bMin)  SLICE_UInt(insn32, (_bMax), (_bMin))
8278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* There are two kinds of instruction to deal with: load/store and
8280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      data processing.  In each case, in ARM mode we merely identify
8281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      the kind, and pass it on to the relevant sub-handler.  In Thumb
8282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      mode we identify the kind, swizzle the bits around to make it
8283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      have the same encoding as in ARM, and hand it on to the
8284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      sub-handler.
8285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   */
8286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* In ARM mode, NEON instructions can't be conditional. */
8288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (!isT)
8289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert(condT == IRTemp_INVALID);
8290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Data processing:
8292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Thumb: 111U 1111 AAAA Axxx xxxx BBBB CCCC xxxx
8293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ARM:   1111 001U AAAA Axxx xxxx BBBB CCCC xxxx
8294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   */
8295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (!isT && INSN(31,25) == BITS7(1,1,1,1,0,0,1)) {
8296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // ARM, DP
8297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return dis_neon_data_processing(INSN(31,0), condT);
8298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
8299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (isT && INSN(31,29) == BITS3(1,1,1)
8300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && INSN(27,24) == BITS4(1,1,1,1)) {
8301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // Thumb, DP
8302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt reformatted = INSN(23,0);
8303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      reformatted |= (INSN(28,28) << 24); // U bit
8304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      reformatted |= (BITS7(1,1,1,1,0,0,1) << 25);
8305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return dis_neon_data_processing(reformatted, condT);
8306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
8307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Load/store:
8309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Thumb: 1111 1001 AxL0 xxxx xxxx BBBB xxxx xxxx
8310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ARM:   1111 0100 AxL0 xxxx xxxx BBBB xxxx xxxx
8311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   */
8312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (!isT && INSN(31,24) == BITS8(1,1,1,1,0,1,0,0)) {
8313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // ARM, memory
8314b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      return dis_neon_load_or_store(INSN(31,0), isT, condT);
8315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
8316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (isT && INSN(31,24) == BITS8(1,1,1,1,1,0,0,1)) {
8317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt reformatted = INSN(23,0);
8318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      reformatted |= (BITS8(1,1,1,1,0,1,0,0) << 24);
8319b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      return dis_neon_load_or_store(reformatted, isT, condT);
8320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
8321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Doesn't match. */
8323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return False;
8324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  undef INSN
8326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
8327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
8330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- V6 MEDIA instructions                                ---*/
8331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
8332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Both ARM and Thumb */
8334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Translate a V6 media instruction.    If successful, returns
8336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   True and *dres may or may not be updated.  If failure, returns
8337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   False and doesn't change *dres nor create any IR.
8338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   The Thumb and ARM encodings are completely different.  In Thumb
8340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   mode, the caller must pass the entire 32 bits.  In ARM mode it must
8341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   pass the lower 28 bits.  Apart from that, callers may pass any
8342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   instruction; this function ignores anything it doesn't recognise.
8343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Caller must supply an IRTemp 'condT' holding the gating condition,
8345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   or IRTemp_INVALID indicating the insn is always executed.
8346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Caller must also supply an ARMCondcode 'cond'.  This is only used
8348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for debug printing, no other purpose.  For ARM, this is simply the
8349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   top 4 bits of the original instruction.  For Thumb, the condition
8350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   is not (really) known until run time, and so ARMCondAL should be
8351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   passed, only so that printing of these instructions does not show
8352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   any condition.
8353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Finally, the caller must indicate whether this occurs in ARM or in
8355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Thumb code.
8356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
8357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool decode_V6MEDIA_instruction (
8358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               /*MOD*/DisResult* dres,
8359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               UInt              insnv6m,
8360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               IRTemp            condT,
8361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               ARMCondcode       conq,
8362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               Bool              isT
8363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            )
8364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
8365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  define INSNA(_bMax,_bMin)   SLICE_UInt(insnv6m, (_bMax), (_bMin))
8366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  define INSNT0(_bMax,_bMin)  SLICE_UInt( ((insnv6m >> 16) & 0xFFFF), \
8367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                           (_bMax), (_bMin) )
8368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  define INSNT1(_bMax,_bMin)  SLICE_UInt( ((insnv6m >> 0)  & 0xFFFF), \
8369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                           (_bMax), (_bMin) )
8370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   HChar dis_buf[128];
8371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   dis_buf[0] = 0;
8372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (isT) {
8374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert(conq == ARMCondAL);
8375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
8376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert(INSNA(31,28) == BITS4(0,0,0,0)); // caller's obligation
8377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert(conq >= ARMCondEQ && conq <= ARMCondAL);
8378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
8379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* ----------- smulbb, smulbt, smultb, smultt ----------- */
8381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   {
8382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     UInt regD = 99, regM = 99, regN = 99, bitM = 0, bitN = 0;
8383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     Bool gate = False;
8384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     if (isT) {
8386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (INSNT0(15,4) == 0xFB1 && INSNT1(15,12) == BITS4(1,1,1,1)
8387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            && INSNT1(7,6) == BITS2(0,0)) {
8388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           regD = INSNT1(11,8);
8389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           regM = INSNT1(3,0);
8390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           regN = INSNT0(3,0);
8391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           bitM = INSNT1(4,4);
8392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           bitN = INSNT1(5,5);
8393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
8394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              gate = True;
8395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
8396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     } else {
8397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (BITS8(0,0,0,1,0,1,1,0) == INSNA(27,20) &&
8398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            BITS4(0,0,0,0)         == INSNA(15,12) &&
8399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            BITS4(1,0,0,0)         == (INSNA(7,4) & BITS4(1,0,0,1)) ) {
8400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           regD = INSNA(19,16);
8401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           regM = INSNA(11,8);
8402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           regN = INSNA(3,0);
8403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           bitM = INSNA(6,6);
8404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           bitN = INSNA(5,5);
8405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           if (regD != 15 && regN != 15 && regM != 15)
8406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              gate = True;
8407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
8408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     }
8409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     if (gate) {
8411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        IRTemp srcN = newTemp(Ity_I32);
8412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        IRTemp srcM = newTemp(Ity_I32);
8413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        IRTemp res  = newTemp(Ity_I32);
8414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        assign( srcN, binop(Iop_Sar32,
8416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            binop(Iop_Shl32,
8417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                  isT ? getIRegT(regN) : getIRegA(regN),
8418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                  mkU8(bitN ? 0 : 16)), mkU8(16)) );
8419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        assign( srcM, binop(Iop_Sar32,
8420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            binop(Iop_Shl32,
8421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                  isT ? getIRegT(regM) : getIRegA(regM),
8422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                  mkU8(bitM ? 0 : 16)), mkU8(16)) );
8423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        assign( res, binop(Iop_Mul32, mkexpr(srcN), mkexpr(srcM)) );
8424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (isT)
8426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           putIRegT( regD, mkexpr(res), condT );
8427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        else
8428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           putIRegA( regD, mkexpr(res), condT, Ijk_Boring );
8429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        DIP( "smul%c%c%s r%u, r%u, r%u\n", bitN ? 't' : 'b', bitM ? 't' : 'b',
8431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             nCC(conq), regD, regN, regM );
8432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        return True;
8433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     }
8434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     /* fall through */
8435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
8436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* ------------ smulwb<y><c> <Rd>,<Rn>,<Rm> ------------- */
8438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* ------------ smulwt<y><c> <Rd>,<Rn>,<Rm> ------------- */
8439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   {
8440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     UInt regD = 99, regN = 99, regM = 99, bitM = 0;
8441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     Bool gate = False;
8442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     if (isT) {
8444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (INSNT0(15,4) == 0xFB3 && INSNT1(15,12) == BITS4(1,1,1,1)
8445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            && INSNT1(7,5) == BITS3(0,0,0)) {
8446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          regN = INSNT0(3,0);
8447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          regD = INSNT1(11,8);
8448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          regM = INSNT1(3,0);
8449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          bitM = INSNT1(4,4);
8450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
8451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             gate = True;
8452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
8453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     } else {
8454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (INSNA(27,20) == BITS8(0,0,0,1,0,0,1,0) &&
8455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            INSNA(15,12) == BITS4(0,0,0,0)         &&
8456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            (INSNA(7,4) & BITS4(1,0,1,1)) == BITS4(1,0,1,0)) {
8457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           regD = INSNA(19,16);
8458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           regN = INSNA(3,0);
8459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           regM = INSNA(11,8);
8460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           bitM = INSNA(6,6);
8461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           if (regD != 15 && regN != 15 && regM != 15)
8462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              gate = True;
8463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
8464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     }
8465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     if (gate) {
8467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        IRTemp irt_prod = newTemp(Ity_I64);
8468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        assign( irt_prod,
8470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                binop(Iop_MullS32,
8471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      isT ? getIRegT(regN) : getIRegA(regN),
8472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      binop(Iop_Sar32,
8473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            binop(Iop_Shl32,
8474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                  isT ? getIRegT(regM) : getIRegA(regM),
8475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                  mkU8(bitM ? 0 : 16)),
8476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            mkU8(16))) );
8477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        IRExpr* ire_result = binop(Iop_Or32,
8479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                   binop( Iop_Shl32,
8480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                          unop(Iop_64HIto32, mkexpr(irt_prod)),
8481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                          mkU8(16) ),
8482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                   binop( Iop_Shr32,
8483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                          unop(Iop_64to32, mkexpr(irt_prod)),
8484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                          mkU8(16) ) );
8485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (isT)
8487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           putIRegT( regD, ire_result, condT );
8488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        else
8489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           putIRegA( regD, ire_result, condT, Ijk_Boring );
8490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        DIP("smulw%c%s r%u, r%u, r%u\n",
8492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            bitM ? 't' : 'b', nCC(conq),regD,regN,regM);
8493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        return True;
8494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     }
8495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     /* fall through */
8496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
8497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* ------------ pkhbt<c> Rd, Rn, Rm {,LSL #imm} ------------- */
8499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* ------------ pkhtb<c> Rd, Rn, Rm {,ASR #imm} ------------- */
8500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   {
8501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     UInt regD = 99, regN = 99, regM = 99, imm5 = 99, shift_type = 99;
8502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     Bool tbform = False;
8503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     Bool gate = False;
8504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     if (isT) {
8506ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (INSNT0(15,4) == 0xEAC
8507ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            && INSNT1(15,15) == 0 && INSNT1(4,4) == 0) {
8508ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           regN = INSNT0(3,0);
8509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           regD = INSNT1(11,8);
8510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           regM = INSNT1(3,0);
8511ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           imm5 = (INSNT1(14,12) << 2) | INSNT1(7,6);
8512ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           shift_type = (INSNT1(5,5) << 1) | 0;
8513ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           tbform = (INSNT1(5,5) == 0) ? False : True;
8514ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
8515ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              gate = True;
8516ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
8517ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     } else {
8518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (INSNA(27,20) == BITS8(0,1,1,0,1,0,0,0) &&
8519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            INSNA(5,4)   == BITS2(0,1)             &&
8520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            (INSNA(6,6)  == 0 || INSNA(6,6) == 1) ) {
8521ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           regD = INSNA(15,12);
8522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           regN = INSNA(19,16);
8523ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           regM = INSNA(3,0);
8524ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           imm5 = INSNA(11,7);
8525ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           shift_type = (INSNA(6,6) << 1) | 0;
8526ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           tbform = (INSNA(6,6) == 0) ? False : True;
8527ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           if (regD != 15 && regN != 15 && regM != 15)
8528ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              gate = True;
8529ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
8530ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     }
8531ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8532ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     if (gate) {
8533ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        IRTemp irt_regM       = newTemp(Ity_I32);
8534ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        IRTemp irt_regM_shift = newTemp(Ity_I32);
8535ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        assign( irt_regM, isT ? getIRegT(regM) : getIRegA(regM) );
8536ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        compute_result_and_C_after_shift_by_imm5(
8537ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           dis_buf, &irt_regM_shift, NULL, irt_regM, shift_type, imm5, regM );
8538ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8539ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        UInt mask = (tbform == True) ? 0x0000FFFF : 0xFFFF0000;
8540ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        IRExpr* ire_result
8541ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          = binop( Iop_Or32,
8542ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   binop(Iop_And32, mkexpr(irt_regM_shift), mkU32(mask)),
8543ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   binop(Iop_And32, isT ? getIRegT(regN) : getIRegA(regN),
8544ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                    unop(Iop_Not32, mkU32(mask))) );
8545ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8546ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (isT)
8547ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           putIRegT( regD, ire_result, condT );
8548ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        else
8549ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           putIRegA( regD, ire_result, condT, Ijk_Boring );
8550ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8551ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        DIP( "pkh%s%s r%u, r%u, r%u %s\n", tbform ? "tb" : "bt",
8552ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             nCC(conq), regD, regN, regM, dis_buf );
8553ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8554ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        return True;
8555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     }
8556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     /* fall through */
8557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
8558ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8559ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* ---------- usat<c> <Rd>,#<imm5>,<Rn>{,<shift>} ----------- */
8560ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   {
8561ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     UInt regD = 99, regN = 99, shift_type = 99, imm5 = 99, sat_imm = 99;
8562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     Bool gate = False;
8563ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8564ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     if (isT) {
8565ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (INSNT0(15,6) == BITS10(1,1,1,1,0,0,1,1,1,0)
8566ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            && INSNT0(4,4) == 0
8567ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            && INSNT1(15,15) == 0 && INSNT1(5,5) == 0) {
8568ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           regD       = INSNT1(11,8);
8569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           regN       = INSNT0(3,0);
8570ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           shift_type = (INSNT0(5,5) << 1) | 0;
8571ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           imm5       = (INSNT1(14,12) << 2) | INSNT1(7,6);
8572ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           sat_imm    = INSNT1(4,0);
8573ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           if (!isBadRegT(regD) && !isBadRegT(regN))
8574ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              gate = True;
8575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           if (shift_type == BITS2(1,0) && imm5 == 0)
8576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              gate = False;
8577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
8578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     } else {
8579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (INSNA(27,21) == BITS7(0,1,1,0,1,1,1) &&
8580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            INSNA(5,4)   == BITS2(0,1)) {
8581ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           regD       = INSNA(15,12);
8582ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           regN       = INSNA(3,0);
8583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           shift_type = (INSNA(6,6) << 1) | 0;
8584ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           imm5       = INSNA(11,7);
8585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           sat_imm    = INSNA(20,16);
8586ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           if (regD != 15 && regN != 15)
8587ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              gate = True;
8588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
8589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     }
8590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     if (gate) {
8592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        IRTemp irt_regN       = newTemp(Ity_I32);
8593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        IRTemp irt_regN_shift = newTemp(Ity_I32);
8594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        IRTemp irt_sat_Q      = newTemp(Ity_I32);
8595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        IRTemp irt_result     = newTemp(Ity_I32);
8596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        assign( irt_regN, isT ? getIRegT(regN) : getIRegA(regN) );
8598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        compute_result_and_C_after_shift_by_imm5(
8599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                dis_buf, &irt_regN_shift, NULL,
8600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                irt_regN, shift_type, imm5, regN );
8601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8602ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        armUnsignedSatQ( &irt_result, &irt_sat_Q, irt_regN_shift, sat_imm );
8603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        or_into_QFLAG32( mkexpr(irt_sat_Q), condT );
8604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8605ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (isT)
8606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           putIRegT( regD, mkexpr(irt_result), condT );
8607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        else
8608ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           putIRegA( regD, mkexpr(irt_result), condT, Ijk_Boring );
8609ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8610ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        DIP("usat%s r%u, #0x%04x, %s\n",
8611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            nCC(conq), regD, imm5, dis_buf);
8612ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        return True;
8613ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     }
8614ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     /* fall through */
8615ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
8616ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8617ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  /* ----------- ssat<c> <Rd>,#<imm5>,<Rn>{,<shift>} ----------- */
8618ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   {
8619ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     UInt regD = 99, regN = 99, shift_type = 99, imm5 = 99, sat_imm = 99;
8620ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     Bool gate = False;
8621ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8622ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     if (isT) {
8623ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (INSNT0(15,6) == BITS10(1,1,1,1,0,0,1,1,0,0)
8624ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            && INSNT0(4,4) == 0
8625ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            && INSNT1(15,15) == 0 && INSNT1(5,5) == 0) {
8626ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           regD       = INSNT1(11,8);
8627ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           regN       = INSNT0(3,0);
8628ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           shift_type = (INSNT0(5,5) << 1) | 0;
8629ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           imm5       = (INSNT1(14,12) << 2) | INSNT1(7,6);
8630ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           sat_imm    = INSNT1(4,0) + 1;
8631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           if (!isBadRegT(regD) && !isBadRegT(regN))
8632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              gate = True;
8633ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           if (shift_type == BITS2(1,0) && imm5 == 0)
8634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              gate = False;
8635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
8636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     } else {
8637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (INSNA(27,21) == BITS7(0,1,1,0,1,0,1) &&
8638ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            INSNA(5,4)   == BITS2(0,1)) {
8639ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           regD       = INSNA(15,12);
8640ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           regN       = INSNA(3,0);
8641ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           shift_type = (INSNA(6,6) << 1) | 0;
8642ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           imm5       = INSNA(11,7);
8643ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           sat_imm    = INSNA(20,16) + 1;
8644ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           if (regD != 15 && regN != 15)
8645ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              gate = True;
8646ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
8647ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     }
8648ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8649ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     if (gate) {
8650ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        IRTemp irt_regN       = newTemp(Ity_I32);
8651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        IRTemp irt_regN_shift = newTemp(Ity_I32);
8652ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        IRTemp irt_sat_Q      = newTemp(Ity_I32);
8653ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        IRTemp irt_result     = newTemp(Ity_I32);
8654ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8655ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        assign( irt_regN, isT ? getIRegT(regN) : getIRegA(regN) );
8656ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        compute_result_and_C_after_shift_by_imm5(
8657ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                dis_buf, &irt_regN_shift, NULL,
8658ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                irt_regN, shift_type, imm5, regN );
8659ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8660ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        armSignedSatQ( irt_regN_shift, sat_imm, &irt_result, &irt_sat_Q );
8661ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        or_into_QFLAG32( mkexpr(irt_sat_Q), condT );
8662ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8663ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (isT)
8664ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           putIRegT( regD, mkexpr(irt_result), condT );
8665ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        else
8666ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           putIRegA( regD, mkexpr(irt_result), condT, Ijk_Boring );
8667ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8668ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        DIP( "ssat%s r%u, #0x%04x, %s\n",
8669ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             nCC(conq), regD, imm5, dis_buf);
8670ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        return True;
8671ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
8672ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* fall through */
8673ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
8674ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8675ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* -------------- usat16<c> <Rd>,#<imm4>,<Rn> --------------- */
8676ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   {
8677ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     UInt regD = 99, regN = 99, sat_imm = 99;
8678ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     Bool gate = False;
8679ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8680ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     if (isT) {
8681ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (INSNT0(15,4) == 0xF3A && (INSNT1(15,0) & 0xF0F0) == 0x0000) {
8682ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           regN = INSNT0(3,0);
8683ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           regD = INSNT1(11,8);
8684ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           sat_imm = INSNT1(3,0);
8685ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           if (!isBadRegT(regD) && !isBadRegT(regN))
8686ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              gate = True;
8687ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       }
8688ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     } else {
8689ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (INSNA(27,20) == BITS8(0,1,1,0,1,1,1,0) &&
8690ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            INSNA(11,8)  == BITS4(1,1,1,1)         &&
8691ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            INSNA(7,4)   == BITS4(0,0,1,1)) {
8692ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           regD    = INSNA(15,12);
8693ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           regN    = INSNA(3,0);
8694ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           sat_imm = INSNA(19,16);
8695ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           if (regD != 15 && regN != 15)
8696ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              gate = True;
8697ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
8698ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     }
8699ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8700ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     if (gate) {
8701ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        IRTemp irt_regN    = newTemp(Ity_I32);
8702ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        IRTemp irt_regN_lo = newTemp(Ity_I32);
8703ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        IRTemp irt_regN_hi = newTemp(Ity_I32);
8704ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        IRTemp irt_Q_lo    = newTemp(Ity_I32);
8705ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        IRTemp irt_Q_hi    = newTemp(Ity_I32);
8706ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        IRTemp irt_res_lo  = newTemp(Ity_I32);
8707ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        IRTemp irt_res_hi  = newTemp(Ity_I32);
8708ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8709ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        assign( irt_regN, isT ? getIRegT(regN) : getIRegA(regN) );
8710ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        assign( irt_regN_lo, binop( Iop_Sar32,
8711ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                    binop(Iop_Shl32, mkexpr(irt_regN), mkU8(16)),
8712ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                    mkU8(16)) );
8713ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        assign( irt_regN_hi, binop(Iop_Sar32, mkexpr(irt_regN), mkU8(16)) );
8714ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8715ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        armUnsignedSatQ( &irt_res_lo, &irt_Q_lo, irt_regN_lo, sat_imm );
8716ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        or_into_QFLAG32( mkexpr(irt_Q_lo), condT );
8717ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8718ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        armUnsignedSatQ( &irt_res_hi, &irt_Q_hi, irt_regN_hi, sat_imm );
8719ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        or_into_QFLAG32( mkexpr(irt_Q_hi), condT );
8720ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8721ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        IRExpr* ire_result = binop( Iop_Or32,
8722ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                    binop(Iop_Shl32, mkexpr(irt_res_hi), mkU8(16)),
8723ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                    mkexpr(irt_res_lo) );
8724ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8725ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (isT)
8726ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           putIRegT( regD, ire_result, condT );
8727ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        else
8728ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           putIRegA( regD, ire_result, condT, Ijk_Boring );
8729ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8730ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        DIP( "usat16%s r%u, #0x%04x, r%u\n", nCC(conq), regD, sat_imm, regN );
8731ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        return True;
8732ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     }
8733ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     /* fall through */
8734ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
8735ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8736ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* -------------- uadd16<c> <Rd>,<Rn>,<Rm> -------------- */
8737ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   {
8738ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     UInt regD = 99, regN = 99, regM = 99;
8739ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     Bool gate = False;
8740ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8741ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     if (isT) {
8742ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (INSNT0(15,4) == 0xFA9 && (INSNT1(15,0) & 0xF0F0) == 0xF040) {
8743ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           regN = INSNT0(3,0);
8744ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           regD = INSNT1(11,8);
8745ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           regM = INSNT1(3,0);
8746ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
8747ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              gate = True;
8748ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
8749ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     } else {
8750ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (INSNA(27,20) == BITS8(0,1,1,0,0,1,0,1) &&
8751ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            INSNA(11,8)  == BITS4(1,1,1,1)         &&
8752ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            INSNA(7,4)   == BITS4(0,0,0,1)) {
8753ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           regD = INSNA(15,12);
8754ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           regN = INSNA(19,16);
8755ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           regM = INSNA(3,0);
8756ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           if (regD != 15 && regN != 15 && regM != 15)
8757ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              gate = True;
8758ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
8759ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     }
8760ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8761ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     if (gate) {
8762ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        IRTemp rNt  = newTemp(Ity_I32);
8763ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        IRTemp rMt  = newTemp(Ity_I32);
8764ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        IRTemp res  = newTemp(Ity_I32);
8765ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        IRTemp reso = newTemp(Ity_I32);
8766ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8767ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) );
8768ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) );
8769ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8770ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        assign(res, binop(Iop_Add16x2, mkexpr(rNt), mkexpr(rMt)));
8771ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (isT)
8772ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           putIRegT( regD, mkexpr(res), condT );
8773ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        else
8774ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           putIRegA( regD, mkexpr(res), condT, Ijk_Boring );
8775ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8776ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        assign(reso, binop(Iop_HAdd16Ux2, mkexpr(rNt), mkexpr(rMt)));
8777ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        set_GE_32_10_from_bits_31_15(reso, condT);
8778ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8779ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        DIP("uadd16%s r%u, r%u, r%u\n", nCC(conq),regD,regN,regM);
8780ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        return True;
8781ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     }
8782ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     /* fall through */
8783ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
8784ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8785ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* -------------- sadd16<c> <Rd>,<Rn>,<Rm> -------------- */
8786ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   {
8787ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     UInt regD = 99, regN = 99, regM = 99;
8788ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     Bool gate = False;
8789ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8790ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     if (isT) {
8791ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (INSNT0(15,4) == 0xFA9 && (INSNT1(15,0) & 0xF0F0) == 0xF000) {
8792ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           regN = INSNT0(3,0);
8793ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           regD = INSNT1(11,8);
8794ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           regM = INSNT1(3,0);
8795ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
8796ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              gate = True;
8797ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
8798ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     } else {
8799ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (INSNA(27,20) == BITS8(0,1,1,0,0,0,0,1) &&
8800ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            INSNA(11,8)  == BITS4(1,1,1,1)         &&
8801ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            INSNA(7,4)   == BITS4(0,0,0,1)) {
8802ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           regD = INSNA(15,12);
8803ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           regN = INSNA(19,16);
8804ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           regM = INSNA(3,0);
8805ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           if (regD != 15 && regN != 15 && regM != 15)
8806ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              gate = True;
8807ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
8808ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     }
8809ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8810ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     if (gate) {
8811ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        IRTemp rNt  = newTemp(Ity_I32);
8812ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        IRTemp rMt  = newTemp(Ity_I32);
8813ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        IRTemp res  = newTemp(Ity_I32);
8814ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        IRTemp reso = newTemp(Ity_I32);
8815ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8816ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) );
8817ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) );
8818ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8819ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        assign(res, binop(Iop_Add16x2, mkexpr(rNt), mkexpr(rMt)));
8820ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (isT)
8821ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           putIRegT( regD, mkexpr(res), condT );
8822ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        else
8823ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           putIRegA( regD, mkexpr(res), condT, Ijk_Boring );
8824ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8825ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        assign(reso, unop(Iop_Not32,
8826ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          binop(Iop_HAdd16Sx2, mkexpr(rNt), mkexpr(rMt))));
8827ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        set_GE_32_10_from_bits_31_15(reso, condT);
8828ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8829ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        DIP("sadd16%s r%u, r%u, r%u\n", nCC(conq),regD,regN,regM);
8830ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        return True;
8831ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     }
8832ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     /* fall through */
8833ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
8834ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8835ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* ---------------- usub16<c> <Rd>,<Rn>,<Rm> ---------------- */
8836ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   {
8837ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     UInt regD = 99, regN = 99, regM = 99;
8838ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     Bool gate = False;
8839ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8840ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     if (isT) {
8841ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (INSNT0(15,4) == 0xFAD && (INSNT1(15,0) & 0xF0F0) == 0xF040) {
8842ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           regN = INSNT0(3,0);
8843ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           regD = INSNT1(11,8);
8844ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           regM = INSNT1(3,0);
8845ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
8846ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              gate = True;
8847ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
8848ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     } else {
8849ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (INSNA(27,20) == BITS8(0,1,1,0,0,1,0,1) &&
8850ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            INSNA(11,8)  == BITS4(1,1,1,1)         &&
8851ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            INSNA(7,4)   == BITS4(0,1,1,1)) {
8852ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           regD = INSNA(15,12);
8853ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           regN = INSNA(19,16);
8854ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           regM = INSNA(3,0);
8855ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           if (regD != 15 && regN != 15 && regM != 15)
8856ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             gate = True;
8857ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
8858ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     }
8859ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8860ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     if (gate) {
8861ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        IRTemp rNt  = newTemp(Ity_I32);
8862ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        IRTemp rMt  = newTemp(Ity_I32);
8863ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        IRTemp res  = newTemp(Ity_I32);
8864ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        IRTemp reso = newTemp(Ity_I32);
8865ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8866ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) );
8867ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) );
8868ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8869ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        assign(res, binop(Iop_Sub16x2, mkexpr(rNt), mkexpr(rMt)));
8870ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (isT)
8871ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           putIRegT( regD, mkexpr(res), condT );
8872ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        else
8873ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           putIRegA( regD, mkexpr(res), condT, Ijk_Boring );
8874ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8875ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        assign(reso, unop(Iop_Not32,
8876ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          binop(Iop_HSub16Ux2, mkexpr(rNt), mkexpr(rMt))));
8877ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        set_GE_32_10_from_bits_31_15(reso, condT);
8878ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8879ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        DIP("usub16%s r%u, r%u, r%u\n", nCC(conq),regD,regN,regM);
8880ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        return True;
8881ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     }
8882ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     /* fall through */
8883ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
8884ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8885ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* -------------- ssub16<c> <Rd>,<Rn>,<Rm> -------------- */
8886ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   {
8887ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     UInt regD = 99, regN = 99, regM = 99;
8888ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     Bool gate = False;
8889ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8890ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     if (isT) {
8891ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (INSNT0(15,4) == 0xFAD && (INSNT1(15,0) & 0xF0F0) == 0xF000) {
8892ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           regN = INSNT0(3,0);
8893ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           regD = INSNT1(11,8);
8894ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           regM = INSNT1(3,0);
8895ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
8896ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              gate = True;
8897ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
8898ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     } else {
8899ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (INSNA(27,20) == BITS8(0,1,1,0,0,0,0,1) &&
8900ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            INSNA(11,8)  == BITS4(1,1,1,1)         &&
8901ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            INSNA(7,4)   == BITS4(0,1,1,1)) {
8902ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           regD = INSNA(15,12);
8903ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           regN = INSNA(19,16);
8904ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           regM = INSNA(3,0);
8905ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           if (regD != 15 && regN != 15 && regM != 15)
8906ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              gate = True;
8907ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
8908ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     }
8909ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8910ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     if (gate) {
8911ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        IRTemp rNt  = newTemp(Ity_I32);
8912ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        IRTemp rMt  = newTemp(Ity_I32);
8913ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        IRTemp res  = newTemp(Ity_I32);
8914ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        IRTemp reso = newTemp(Ity_I32);
8915ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8916ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) );
8917ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) );
8918ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8919ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        assign(res, binop(Iop_Sub16x2, mkexpr(rNt), mkexpr(rMt)));
8920ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (isT)
8921ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           putIRegT( regD, mkexpr(res), condT );
8922ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        else
8923ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           putIRegA( regD, mkexpr(res), condT, Ijk_Boring );
8924ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8925ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        assign(reso, unop(Iop_Not32,
8926ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          binop(Iop_HSub16Sx2, mkexpr(rNt), mkexpr(rMt))));
8927ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        set_GE_32_10_from_bits_31_15(reso, condT);
8928ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8929ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        DIP("ssub16%s r%u, r%u, r%u\n", nCC(conq),regD,regN,regM);
8930ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        return True;
8931ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     }
8932ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     /* fall through */
8933ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
8934ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8935ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* ----------------- uadd8<c> <Rd>,<Rn>,<Rm> ---------------- */
8936ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   {
8937ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     UInt regD = 99, regN = 99, regM = 99;
8938ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     Bool gate = False;
8939ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8940ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     if (isT) {
8941ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (INSNT0(15,4) == 0xFA8 && (INSNT1(15,0) & 0xF0F0) == 0xF040) {
8942ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           regN = INSNT0(3,0);
8943ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           regD = INSNT1(11,8);
8944ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           regM = INSNT1(3,0);
8945ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
8946ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              gate = True;
8947ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
8948ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     } else {
8949ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (INSNA(27,20) == BITS8(0,1,1,0,0,1,0,1) &&
8950ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            INSNA(11,8)  == BITS4(1,1,1,1)         &&
8951ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            (INSNA(7,4)  == BITS4(1,0,0,1))) {
8952ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           regD = INSNA(15,12);
8953ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           regN = INSNA(19,16);
8954ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           regM = INSNA(3,0);
8955ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           if (regD != 15 && regN != 15 && regM != 15)
8956ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              gate = True;
8957ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
8958ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     }
8959ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8960ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     if (gate) {
8961ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        IRTemp rNt  = newTemp(Ity_I32);
8962ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        IRTemp rMt  = newTemp(Ity_I32);
8963ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        IRTemp res  = newTemp(Ity_I32);
8964ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        IRTemp reso = newTemp(Ity_I32);
8965ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8966ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) );
8967ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) );
8968ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8969ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        assign(res, binop(Iop_Add8x4, mkexpr(rNt), mkexpr(rMt)));
8970ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (isT)
8971ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           putIRegT( regD, mkexpr(res), condT );
8972ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        else
8973ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           putIRegA( regD, mkexpr(res), condT, Ijk_Boring );
8974ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8975ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        assign(reso, binop(Iop_HAdd8Ux4, mkexpr(rNt), mkexpr(rMt)));
8976ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        set_GE_3_2_1_0_from_bits_31_23_15_7(reso, condT);
8977ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8978ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        DIP("uadd8%s r%u, r%u, r%u\n", nCC(conq),regD,regN,regM);
8979ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        return True;
8980ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     }
8981ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     /* fall through */
8982ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
8983ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8984ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* ------------------- sadd8<c> <Rd>,<Rn>,<Rm> ------------------ */
8985ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   {
8986ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     UInt regD = 99, regN = 99, regM = 99;
8987ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     Bool gate = False;
8988ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8989ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     if (isT) {
8990ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (INSNT0(15,4) == 0xFA8 && (INSNT1(15,0) & 0xF0F0) == 0xF000) {
8991ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           regN = INSNT0(3,0);
8992ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           regD = INSNT1(11,8);
8993ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           regM = INSNT1(3,0);
8994ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
8995ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              gate = True;
8996ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
8997ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     } else {
8998ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (INSNA(27,20) == BITS8(0,1,1,0,0,0,0,1) &&
8999ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            INSNA(11,8)  == BITS4(1,1,1,1)         &&
9000ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            (INSNA(7,4)  == BITS4(1,0,0,1))) {
9001ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           regD = INSNA(15,12);
9002ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           regN = INSNA(19,16);
9003ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           regM = INSNA(3,0);
9004ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           if (regD != 15 && regN != 15 && regM != 15)
9005ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              gate = True;
9006ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
9007ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     }
9008ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9009ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     if (gate) {
9010ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        IRTemp rNt  = newTemp(Ity_I32);
9011ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        IRTemp rMt  = newTemp(Ity_I32);
9012ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        IRTemp res  = newTemp(Ity_I32);
9013ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        IRTemp reso = newTemp(Ity_I32);
9014ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9015ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) );
9016ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) );
9017ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9018ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        assign(res, binop(Iop_Add8x4, mkexpr(rNt), mkexpr(rMt)));
9019ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (isT)
9020ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           putIRegT( regD, mkexpr(res), condT );
9021ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        else
9022ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           putIRegA( regD, mkexpr(res), condT, Ijk_Boring );
9023ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9024ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        assign(reso, unop(Iop_Not32,
9025ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          binop(Iop_HAdd8Sx4, mkexpr(rNt), mkexpr(rMt))));
9026ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        set_GE_3_2_1_0_from_bits_31_23_15_7(reso, condT);
9027ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9028ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        DIP("sadd8%s r%u, r%u, r%u\n", nCC(conq),regD,regN,regM);
9029ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        return True;
9030ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     }
9031ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     /* fall through */
9032ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
9033ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9034ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* ------------------- usub8<c> <Rd>,<Rn>,<Rm> ------------------ */
9035ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   {
9036ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     UInt regD = 99, regN = 99, regM = 99;
9037ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     Bool gate = False;
9038ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9039ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     if (isT) {
9040ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (INSNT0(15,4) == 0xFAC && (INSNT1(15,0) & 0xF0F0) == 0xF040) {
9041ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           regN = INSNT0(3,0);
9042ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           regD = INSNT1(11,8);
9043ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           regM = INSNT1(3,0);
9044ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
9045ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              gate = True;
9046ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
9047ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     } else {
9048ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (INSNA(27,20) == BITS8(0,1,1,0,0,1,0,1) &&
9049ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            INSNA(11,8)  == BITS4(1,1,1,1)         &&
9050ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            (INSNA(7,4)  == BITS4(1,1,1,1))) {
9051ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           regD = INSNA(15,12);
9052ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           regN = INSNA(19,16);
9053ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           regM = INSNA(3,0);
9054ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           if (regD != 15 && regN != 15 && regM != 15)
9055ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             gate = True;
9056ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
9057ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     }
9058ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9059ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     if (gate) {
9060ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        IRTemp rNt  = newTemp(Ity_I32);
9061ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        IRTemp rMt  = newTemp(Ity_I32);
9062ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        IRTemp res  = newTemp(Ity_I32);
9063ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        IRTemp reso = newTemp(Ity_I32);
9064ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9065ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) );
9066ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) );
9067ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9068ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        assign(res, binop(Iop_Sub8x4, mkexpr(rNt), mkexpr(rMt)));
9069ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (isT)
9070ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           putIRegT( regD, mkexpr(res), condT );
9071ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        else
9072ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           putIRegA( regD, mkexpr(res), condT, Ijk_Boring );
9073ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9074ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        assign(reso, unop(Iop_Not32,
9075ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          binop(Iop_HSub8Ux4, mkexpr(rNt), mkexpr(rMt))));
9076ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        set_GE_3_2_1_0_from_bits_31_23_15_7(reso, condT);
9077ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9078ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        DIP("usub8%s r%u, r%u, r%u\n", nCC(conq),regD,regN,regM);
9079ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        return True;
9080ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     }
9081ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     /* fall through */
9082ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
9083ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9084ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* ------------------- ssub8<c> <Rd>,<Rn>,<Rm> ------------------ */
9085ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   {
9086ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     UInt regD = 99, regN = 99, regM = 99;
9087ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     Bool gate = False;
9088ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9089ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     if (isT) {
9090ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (INSNT0(15,4) == 0xFAC && (INSNT1(15,0) & 0xF0F0) == 0xF000) {
9091ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           regN = INSNT0(3,0);
9092ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           regD = INSNT1(11,8);
9093ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           regM = INSNT1(3,0);
9094ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
9095ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              gate = True;
9096ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
9097ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     } else {
9098ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (INSNA(27,20) == BITS8(0,1,1,0,0,0,0,1) &&
9099ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            INSNA(11,8)  == BITS4(1,1,1,1)         &&
9100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            INSNA(7,4)   == BITS4(1,1,1,1)) {
9101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           regD = INSNA(15,12);
9102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           regN = INSNA(19,16);
9103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           regM = INSNA(3,0);
9104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           if (regD != 15 && regN != 15 && regM != 15)
9105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              gate = True;
9106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
9107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     }
9108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     if (gate) {
9110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        IRTemp rNt  = newTemp(Ity_I32);
9111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        IRTemp rMt  = newTemp(Ity_I32);
9112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        IRTemp res  = newTemp(Ity_I32);
9113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        IRTemp reso = newTemp(Ity_I32);
9114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) );
9116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) );
9117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        assign(res, binop(Iop_Sub8x4, mkexpr(rNt), mkexpr(rMt)));
9119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (isT)
9120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           putIRegT( regD, mkexpr(res), condT );
9121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        else
9122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           putIRegA( regD, mkexpr(res), condT, Ijk_Boring );
9123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        assign(reso, unop(Iop_Not32,
9125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          binop(Iop_HSub8Sx4, mkexpr(rNt), mkexpr(rMt))));
9126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        set_GE_3_2_1_0_from_bits_31_23_15_7(reso, condT);
9127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        DIP("ssub8%s r%u, r%u, r%u\n", nCC(conq),regD,regN,regM);
9129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        return True;
9130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     }
9131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     /* fall through */
9132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
9133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* ------------------ qadd8<c> <Rd>,<Rn>,<Rm> ------------------- */
9135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   {
9136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     UInt regD = 99, regN = 99, regM = 99;
9137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     Bool gate = False;
9138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     if (isT) {
9140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (INSNT0(15,4) == 0xFA8 && (INSNT1(15,0) & 0xF0F0) == 0xF010) {
9141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           regN = INSNT0(3,0);
9142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           regD = INSNT1(11,8);
9143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           regM = INSNT1(3,0);
9144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
9145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              gate = True;
9146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
9147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     } else {
9148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (INSNA(27,20) == BITS8(0,1,1,0,0,0,1,0) &&
9149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            INSNA(11,8)  == BITS4(1,1,1,1)         &&
9150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            INSNA(7,4)   == BITS4(1,0,0,1)) {
9151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           regD = INSNA(15,12);
9152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           regN = INSNA(19,16);
9153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           regM = INSNA(3,0);
9154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           if (regD != 15 && regN != 15 && regM != 15)
9155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              gate = True;
9156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
9157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     }
9158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     if (gate) {
9160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        IRTemp rNt   = newTemp(Ity_I32);
9161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        IRTemp rMt   = newTemp(Ity_I32);
9162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        IRTemp res_q = newTemp(Ity_I32);
9163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) );
9165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) );
9166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        assign(res_q, binop(Iop_QAdd8Sx4, mkexpr(rNt), mkexpr(rMt)));
9168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (isT)
9169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           putIRegT( regD, mkexpr(res_q), condT );
9170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        else
9171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           putIRegA( regD, mkexpr(res_q), condT, Ijk_Boring );
9172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        DIP("qadd8%s r%u, r%u, r%u\n", nCC(conq),regD,regN,regM);
9174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        return True;
9175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     }
9176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     /* fall through */
9177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
9178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* ------------------ qsub8<c> <Rd>,<Rn>,<Rm> ------------------- */
9180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   {
9181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     UInt regD = 99, regN = 99, regM = 99;
9182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     Bool gate = False;
9183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     if (isT) {
9185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (INSNT0(15,4) == 0xFAC && (INSNT1(15,0) & 0xF0F0) == 0xF010) {
9186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           regN = INSNT0(3,0);
9187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           regD = INSNT1(11,8);
9188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           regM = INSNT1(3,0);
9189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
9190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              gate = True;
9191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
9192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     } else {
9193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (INSNA(27,20) == BITS8(0,1,1,0,0,0,1,0) &&
9194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            INSNA(11,8)  == BITS4(1,1,1,1)         &&
9195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            INSNA(7,4)   == BITS4(1,1,1,1)) {
9196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           regD = INSNA(15,12);
9197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           regN = INSNA(19,16);
9198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           regM = INSNA(3,0);
9199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           if (regD != 15 && regN != 15 && regM != 15)
9200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              gate = True;
9201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
9202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     }
9203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     if (gate) {
9205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        IRTemp rNt   = newTemp(Ity_I32);
9206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        IRTemp rMt   = newTemp(Ity_I32);
9207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        IRTemp res_q = newTemp(Ity_I32);
9208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) );
9210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) );
9211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        assign(res_q, binop(Iop_QSub8Sx4, mkexpr(rNt), mkexpr(rMt)));
9213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (isT)
9214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           putIRegT( regD, mkexpr(res_q), condT );
9215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        else
9216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           putIRegA( regD, mkexpr(res_q), condT, Ijk_Boring );
9217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        DIP("qsub8%s r%u, r%u, r%u\n", nCC(conq),regD,regN,regM);
9219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        return True;
9220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     }
9221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     /* fall through */
9222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
9223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* ------------------ uqadd8<c> <Rd>,<Rn>,<Rm> ------------------ */
9225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   {
9226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     UInt regD = 99, regN = 99, regM = 99;
9227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     Bool gate = False;
9228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     if (isT) {
9230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (INSNT0(15,4) == 0xFA8 && (INSNT1(15,0) & 0xF0F0) == 0xF050) {
9231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           regN = INSNT0(3,0);
9232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           regD = INSNT1(11,8);
9233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           regM = INSNT1(3,0);
9234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
9235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              gate = True;
9236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
9237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     } else {
9238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (INSNA(27,20) == BITS8(0,1,1,0,0,1,1,0) &&
9239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            INSNA(11,8)  == BITS4(1,1,1,1)         &&
9240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            (INSNA(7,4)  == BITS4(1,0,0,1))) {
9241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           regD = INSNA(15,12);
9242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           regN = INSNA(19,16);
9243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           regM = INSNA(3,0);
9244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           if (regD != 15 && regN != 15 && regM != 15)
9245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              gate = True;
9246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
9247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     }
9248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     if (gate) {
9250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        IRTemp rNt   = newTemp(Ity_I32);
9251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        IRTemp rMt   = newTemp(Ity_I32);
9252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        IRTemp res_q = newTemp(Ity_I32);
9253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) );
9255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) );
9256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        assign(res_q, binop(Iop_QAdd8Ux4, mkexpr(rNt), mkexpr(rMt)));
9258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (isT)
9259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           putIRegT( regD, mkexpr(res_q), condT );
9260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        else
9261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           putIRegA( regD, mkexpr(res_q), condT, Ijk_Boring );
9262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        DIP("uqadd8%s r%u, r%u, r%u\n", nCC(conq),regD,regN,regM);
9264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        return True;
9265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     }
9266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     /* fall through */
9267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
9268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* ------------------ uqsub8<c> <Rd>,<Rn>,<Rm> ------------------ */
9270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   {
9271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     UInt regD = 99, regN = 99, regM = 99;
9272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     Bool gate = False;
9273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     if (isT) {
9275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (INSNT0(15,4) == 0xFAC && (INSNT1(15,0) & 0xF0F0) == 0xF050) {
9276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           regN = INSNT0(3,0);
9277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           regD = INSNT1(11,8);
9278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           regM = INSNT1(3,0);
9279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
9280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              gate = True;
9281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
9282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     } else {
9283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (INSNA(27,20) == BITS8(0,1,1,0,0,1,1,0) &&
9284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            INSNA(11,8)  == BITS4(1,1,1,1)         &&
9285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            (INSNA(7,4)  == BITS4(1,1,1,1))) {
9286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           regD = INSNA(15,12);
9287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           regN = INSNA(19,16);
9288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           regM = INSNA(3,0);
9289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           if (regD != 15 && regN != 15 && regM != 15)
9290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             gate = True;
9291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
9292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     }
9293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     if (gate) {
9295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        IRTemp rNt   = newTemp(Ity_I32);
9296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        IRTemp rMt   = newTemp(Ity_I32);
9297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        IRTemp res_q = newTemp(Ity_I32);
9298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) );
9300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) );
9301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        assign(res_q, binop(Iop_QSub8Ux4, mkexpr(rNt), mkexpr(rMt)));
9303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (isT)
9304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           putIRegT( regD, mkexpr(res_q), condT );
9305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        else
9306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           putIRegA( regD, mkexpr(res_q), condT, Ijk_Boring );
9307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        DIP("uqsub8%s r%u, r%u, r%u\n", nCC(conq),regD,regN,regM);
9309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        return True;
9310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     }
9311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     /* fall through */
9312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
9313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* ----------------- uhadd8<c> <Rd>,<Rn>,<Rm> ------------------- */
9315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   {
9316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     UInt regD = 99, regN = 99, regM = 99;
9317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     Bool gate = False;
9318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     if (isT) {
9320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (INSNT0(15,4) == 0xFA8 && (INSNT1(15,0) & 0xF0F0) == 0xF060) {
9321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           regN = INSNT0(3,0);
9322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           regD = INSNT1(11,8);
9323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           regM = INSNT1(3,0);
9324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
9325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              gate = True;
9326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
9327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     } else {
9328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (INSNA(27,20) == BITS8(0,1,1,0,0,1,1,1) &&
9329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            INSNA(11,8)  == BITS4(1,1,1,1)         &&
9330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            INSNA(7,4)   == BITS4(1,0,0,1)) {
9331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           regD = INSNA(15,12);
9332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           regN = INSNA(19,16);
9333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           regM = INSNA(3,0);
9334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           if (regD != 15 && regN != 15 && regM != 15)
9335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              gate = True;
9336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
9337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     }
9338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     if (gate) {
9340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        IRTemp rNt   = newTemp(Ity_I32);
9341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        IRTemp rMt   = newTemp(Ity_I32);
9342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        IRTemp res_q = newTemp(Ity_I32);
9343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) );
9345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) );
9346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        assign(res_q, binop(Iop_HAdd8Ux4, mkexpr(rNt), mkexpr(rMt)));
9348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (isT)
9349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           putIRegT( regD, mkexpr(res_q), condT );
9350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        else
9351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           putIRegA( regD, mkexpr(res_q), condT, Ijk_Boring );
9352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        DIP("uhadd8%s r%u, r%u, r%u\n", nCC(conq),regD,regN,regM);
9354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        return True;
9355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     }
9356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     /* fall through */
9357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
9358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9359663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* ----------------- uhadd16<c> <Rd>,<Rn>,<Rm> ------------------- */
9360663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   {
9361663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng     UInt regD = 99, regN = 99, regM = 99;
9362663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng     Bool gate = False;
9363663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
9364663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng     if (isT) {
9365663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        if (INSNT0(15,4) == 0xFA9 && (INSNT1(15,0) & 0xF0F0) == 0xF060) {
9366663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng           regN = INSNT0(3,0);
9367663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng           regD = INSNT1(11,8);
9368663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng           regM = INSNT1(3,0);
9369663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng           if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
9370663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng              gate = True;
9371663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        }
9372663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng     } else {
9373663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        if (INSNA(27,20) == BITS8(0,1,1,0,0,1,1,1) &&
9374663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            INSNA(11,8)  == BITS4(1,1,1,1)         &&
9375663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            INSNA(7,4)   == BITS4(0,0,0,1)) {
9376663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng           regD = INSNA(15,12);
9377663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng           regN = INSNA(19,16);
9378663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng           regM = INSNA(3,0);
9379663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng           if (regD != 15 && regN != 15 && regM != 15)
9380663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng              gate = True;
9381663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        }
9382663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng     }
9383663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
9384663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng     if (gate) {
9385663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        IRTemp rNt   = newTemp(Ity_I32);
9386663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        IRTemp rMt   = newTemp(Ity_I32);
9387663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        IRTemp res_q = newTemp(Ity_I32);
9388663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
9389663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) );
9390663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) );
9391663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
9392663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        assign(res_q, binop(Iop_HAdd16Ux2, mkexpr(rNt), mkexpr(rMt)));
9393663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        if (isT)
9394663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng           putIRegT( regD, mkexpr(res_q), condT );
9395663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        else
9396663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng           putIRegA( regD, mkexpr(res_q), condT, Ijk_Boring );
9397663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
9398663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        DIP("uhadd16%s r%u, r%u, r%u\n", nCC(conq),regD,regN,regM);
9399663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        return True;
9400663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng     }
9401663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng     /* fall through */
9402663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
9403663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
9404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* ----------------- shadd8<c> <Rd>,<Rn>,<Rm> ------------------- */
9405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   {
9406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     UInt regD = 99, regN = 99, regM = 99;
9407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     Bool gate = False;
9408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     if (isT) {
9410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (INSNT0(15,4) == 0xFA8 && (INSNT1(15,0) & 0xF0F0) == 0xF020) {
9411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           regN = INSNT0(3,0);
9412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           regD = INSNT1(11,8);
9413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           regM = INSNT1(3,0);
9414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
9415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              gate = True;
9416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
9417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     } else {
9418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (INSNA(27,20) == BITS8(0,1,1,0,0,0,1,1) &&
9419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            INSNA(11,8)  == BITS4(1,1,1,1)         &&
9420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            INSNA(7,4)   == BITS4(1,0,0,1)) {
9421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           regD = INSNA(15,12);
9422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           regN = INSNA(19,16);
9423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           regM = INSNA(3,0);
9424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           if (regD != 15 && regN != 15 && regM != 15)
9425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              gate = True;
9426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
9427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     }
9428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     if (gate) {
9430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        IRTemp rNt   = newTemp(Ity_I32);
9431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        IRTemp rMt   = newTemp(Ity_I32);
9432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        IRTemp res_q = newTemp(Ity_I32);
9433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) );
9435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) );
9436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        assign(res_q, binop(Iop_HAdd8Sx4, mkexpr(rNt), mkexpr(rMt)));
9438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (isT)
9439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           putIRegT( regD, mkexpr(res_q), condT );
9440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        else
9441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           putIRegA( regD, mkexpr(res_q), condT, Ijk_Boring );
9442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        DIP("shadd8%s r%u, r%u, r%u\n", nCC(conq),regD,regN,regM);
9444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        return True;
9445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     }
9446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     /* fall through */
9447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
9448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* ------------------ qadd16<c> <Rd>,<Rn>,<Rm> ------------------ */
9450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   {
9451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     UInt regD = 99, regN = 99, regM = 99;
9452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     Bool gate = False;
9453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     if (isT) {
9455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (INSNT0(15,4) == 0xFA9 && (INSNT1(15,0) & 0xF0F0) == 0xF010) {
9456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           regN = INSNT0(3,0);
9457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           regD = INSNT1(11,8);
9458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           regM = INSNT1(3,0);
9459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
9460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              gate = True;
9461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
9462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     } else {
9463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (INSNA(27,20) == BITS8(0,1,1,0,0,0,1,0) &&
9464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            INSNA(11,8)  == BITS4(1,1,1,1)         &&
9465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            INSNA(7,4)   == BITS4(0,0,0,1)) {
9466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           regD = INSNA(15,12);
9467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           regN = INSNA(19,16);
9468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           regM = INSNA(3,0);
9469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           if (regD != 15 && regN != 15 && regM != 15)
9470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              gate = True;
9471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
9472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     }
9473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     if (gate) {
9475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        IRTemp rNt   = newTemp(Ity_I32);
9476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        IRTemp rMt   = newTemp(Ity_I32);
9477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        IRTemp res_q = newTemp(Ity_I32);
9478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) );
9480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) );
9481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        assign(res_q, binop(Iop_QAdd16Sx2, mkexpr(rNt), mkexpr(rMt)));
9483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (isT)
9484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           putIRegT( regD, mkexpr(res_q), condT );
9485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        else
9486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           putIRegA( regD, mkexpr(res_q), condT, Ijk_Boring );
9487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        DIP("qadd16%s r%u, r%u, r%u\n", nCC(conq),regD,regN,regM);
9489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        return True;
9490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     }
9491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     /* fall through */
9492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
9493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* ------------------ qsub16<c> <Rd>,<Rn>,<Rm> ------------------ */
9495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   {
9496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     UInt regD = 99, regN = 99, regM = 99;
9497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     Bool gate = False;
9498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (isT) {
9500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (INSNT0(15,4) == 0xFAD && (INSNT1(15,0) & 0xF0F0) == 0xF010) {
9501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           regN = INSNT0(3,0);
9502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           regD = INSNT1(11,8);
9503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           regM = INSNT1(3,0);
9504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
9505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              gate = True;
9506ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
9507ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     } else {
9508ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (INSNA(27,20) == BITS8(0,1,1,0,0,0,1,0) &&
9509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            INSNA(11,8)  == BITS4(1,1,1,1)         &&
9510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            INSNA(7,4)   == BITS4(0,1,1,1)) {
9511ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           regD = INSNA(15,12);
9512ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           regN = INSNA(19,16);
9513ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           regM = INSNA(3,0);
9514ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           if (regD != 15 && regN != 15 && regM != 15)
9515ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             gate = True;
9516ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
9517ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     }
9518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     if (gate) {
9520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        IRTemp rNt   = newTemp(Ity_I32);
9521ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        IRTemp rMt   = newTemp(Ity_I32);
9522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        IRTemp res_q = newTemp(Ity_I32);
9523ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9524ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) );
9525ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) );
9526ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9527ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        assign(res_q, binop(Iop_QSub16Sx2, mkexpr(rNt), mkexpr(rMt)));
9528ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (isT)
9529ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           putIRegT( regD, mkexpr(res_q), condT );
9530ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        else
9531ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           putIRegA( regD, mkexpr(res_q), condT, Ijk_Boring );
9532ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9533ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        DIP("qsub16%s r%u, r%u, r%u\n", nCC(conq),regD,regN,regM);
9534ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        return True;
9535ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     }
9536ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     /* fall through */
9537ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
9538ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9539ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /////////////////////////////////////////////////////////////////
9540ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /////////////////////////////////////////////////////////////////
9541ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /////////////////////////////////////////////////////////////////
9542ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /////////////////////////////////////////////////////////////////
9543ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /////////////////////////////////////////////////////////////////
9544ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9545ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* ------------------- qsax<c> <Rd>,<Rn>,<Rm> ------------------- */
9546ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* note: the hardware seems to construct the result differently
9547ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      from wot the manual says. */
9548ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   {
9549ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     UInt regD = 99, regN = 99, regM = 99;
9550ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     Bool gate = False;
9551ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9552ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     if (isT) {
9553ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (INSNT0(15,4) == 0xFAE && (INSNT1(15,0) & 0xF0F0) == 0xF010) {
9554ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           regN = INSNT0(3,0);
9555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           regD = INSNT1(11,8);
9556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           regM = INSNT1(3,0);
9557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
9558ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              gate = True;
9559ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
9560ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     } else {
9561ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (INSNA(27,20) == BITS8(0,1,1,0,0,0,1,0) &&
9562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            INSNA(11,8)  == BITS4(1,1,1,1)         &&
9563ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            INSNA(7,4)   == BITS4(0,1,0,1)) {
9564ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           regD = INSNA(15,12);
9565ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           regN = INSNA(19,16);
9566ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           regM = INSNA(3,0);
9567ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           if (regD != 15 && regN != 15 && regM != 15)
9568ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              gate = True;
9569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
9570ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     }
9571ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9572ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     if (gate) {
9573ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        IRTemp irt_regN     = newTemp(Ity_I32);
9574ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        IRTemp irt_regM     = newTemp(Ity_I32);
9575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        IRTemp irt_sum      = newTemp(Ity_I32);
9576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        IRTemp irt_diff     = newTemp(Ity_I32);
9577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        IRTemp irt_sum_res  = newTemp(Ity_I32);
9578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        IRTemp irt_diff_res = newTemp(Ity_I32);
9579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        assign( irt_regN, isT ? getIRegT(regN) : getIRegA(regN) );
9581ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        assign( irt_regM, isT ? getIRegT(regM) : getIRegA(regM) );
9582ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        assign( irt_diff,
9584ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                binop( Iop_Sub32,
9585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       binop( Iop_Sar32, mkexpr(irt_regN), mkU8(16) ),
9586ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       binop( Iop_Sar32,
9587ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              binop(Iop_Shl32, mkexpr(irt_regM), mkU8(16)),
9588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              mkU8(16) ) ) );
9589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        armSignedSatQ( irt_diff, 0x10, &irt_diff_res, NULL);
9590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        assign( irt_sum,
9592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                binop( Iop_Add32,
9593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       binop( Iop_Sar32,
9594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              binop( Iop_Shl32, mkexpr(irt_regN), mkU8(16) ),
9595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              mkU8(16) ),
9596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       binop( Iop_Sar32, mkexpr(irt_regM), mkU8(16) )) );
9597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        armSignedSatQ( irt_sum, 0x10, &irt_sum_res, NULL );
9598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        IRExpr* ire_result = binop( Iop_Or32,
9600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                    binop( Iop_Shl32, mkexpr(irt_diff_res),
9601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                           mkU8(16) ),
9602ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                    binop( Iop_And32, mkexpr(irt_sum_res),
9603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                           mkU32(0xFFFF)) );
9604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9605ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (isT)
9606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           putIRegT( regD, ire_result, condT );
9607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        else
9608ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           putIRegA( regD, ire_result, condT, Ijk_Boring );
9609ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9610ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        DIP( "qsax%s r%u, r%u, r%u\n", nCC(conq), regD, regN, regM );
9611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        return True;
9612ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     }
9613ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     /* fall through */
9614ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
9615ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9616ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* ------------------- qasx<c> <Rd>,<Rn>,<Rm> ------------------- */
9617ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   {
9618ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     UInt regD = 99, regN = 99, regM = 99;
9619ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     Bool gate = False;
9620ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9621ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     if (isT) {
9622ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (INSNT0(15,4) == 0xFAA && (INSNT1(15,0) & 0xF0F0) == 0xF010) {
9623ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           regN = INSNT0(3,0);
9624ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           regD = INSNT1(11,8);
9625ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           regM = INSNT1(3,0);
9626ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
9627ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              gate = True;
9628ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
9629ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     } else {
9630ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (INSNA(27,20) == BITS8(0,1,1,0,0,0,1,0) &&
9631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            INSNA(11,8)  == BITS4(1,1,1,1)         &&
9632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            INSNA(7,4)   == BITS4(0,0,1,1)) {
9633ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           regD = INSNA(15,12);
9634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           regN = INSNA(19,16);
9635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           regM = INSNA(3,0);
9636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           if (regD != 15 && regN != 15 && regM != 15)
9637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              gate = True;
9638ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
9639ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     }
9640ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9641ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     if (gate) {
9642ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        IRTemp irt_regN     = newTemp(Ity_I32);
9643ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        IRTemp irt_regM     = newTemp(Ity_I32);
9644ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        IRTemp irt_sum      = newTemp(Ity_I32);
9645ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        IRTemp irt_diff     = newTemp(Ity_I32);
9646ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        IRTemp irt_res_sum  = newTemp(Ity_I32);
9647ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        IRTemp irt_res_diff = newTemp(Ity_I32);
9648ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9649ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        assign( irt_regN, isT ? getIRegT(regN) : getIRegA(regN) );
9650ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        assign( irt_regM, isT ? getIRegT(regM) : getIRegA(regM) );
9651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9652ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        assign( irt_diff,
9653ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                binop( Iop_Sub32,
9654ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       binop( Iop_Sar32,
9655ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              binop( Iop_Shl32, mkexpr(irt_regN), mkU8(16) ),
9656ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              mkU8(16) ),
9657ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       binop( Iop_Sar32, mkexpr(irt_regM), mkU8(16) ) ) );
9658ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        armSignedSatQ( irt_diff, 0x10, &irt_res_diff, NULL );
9659ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9660ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        assign( irt_sum,
9661ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                binop( Iop_Add32,
9662ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       binop( Iop_Sar32, mkexpr(irt_regN), mkU8(16) ),
9663ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       binop( Iop_Sar32,
9664ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              binop( Iop_Shl32, mkexpr(irt_regM), mkU8(16) ),
9665ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              mkU8(16) ) ) );
9666ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        armSignedSatQ( irt_sum, 0x10, &irt_res_sum, NULL );
9667ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9668ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        IRExpr* ire_result
9669ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          = binop( Iop_Or32,
9670ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   binop( Iop_Shl32, mkexpr(irt_res_sum), mkU8(16) ),
9671ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   binop( Iop_And32, mkexpr(irt_res_diff), mkU32(0xFFFF) ) );
9672ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9673ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (isT)
9674ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           putIRegT( regD, ire_result, condT );
9675ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        else
9676ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           putIRegA( regD, ire_result, condT, Ijk_Boring );
9677ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9678ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        DIP( "qasx%s r%u, r%u, r%u\n", nCC(conq), regD, regN, regM );
9679ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        return True;
9680ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     }
9681ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     /* fall through */
9682ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
9683ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9684ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* ------------------- sasx<c> <Rd>,<Rn>,<Rm> ------------------- */
9685ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   {
9686ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     UInt regD = 99, regN = 99, regM = 99;
9687ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     Bool gate = False;
9688ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9689ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     if (isT) {
9690ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (INSNT0(15,4) == 0xFAA && (INSNT1(15,0) & 0xF0F0) == 0xF000) {
9691ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           regN = INSNT0(3,0);
9692ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           regD = INSNT1(11,8);
9693ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           regM = INSNT1(3,0);
9694ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
9695ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              gate = True;
9696ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
9697ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     } else {
9698ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (INSNA(27,20) == BITS8(0,1,1,0,0,0,0,1) &&
9699ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            INSNA(11,8)  == BITS4(1,1,1,1)         &&
9700ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            INSNA(7,4)   == BITS4(0,0,1,1)) {
9701ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           regD = INSNA(15,12);
9702ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           regN = INSNA(19,16);
9703ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           regM = INSNA(3,0);
9704ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           if (regD != 15 && regN != 15 && regM != 15)
9705ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              gate = True;
9706ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
9707ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     }
9708ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9709ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     if (gate) {
9710ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        IRTemp irt_regN = newTemp(Ity_I32);
9711ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        IRTemp irt_regM = newTemp(Ity_I32);
9712ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        IRTemp irt_sum  = newTemp(Ity_I32);
9713ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        IRTemp irt_diff = newTemp(Ity_I32);
9714ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9715ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        assign( irt_regN, isT ? getIRegT(regN) : getIRegA(regN) );
9716ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        assign( irt_regM, isT ? getIRegT(regM) : getIRegA(regM) );
9717ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9718ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        assign( irt_diff,
9719ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                binop( Iop_Sub32,
9720ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       binop( Iop_Sar32,
9721ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              binop( Iop_Shl32, mkexpr(irt_regN), mkU8(16) ),
9722ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              mkU8(16) ),
9723ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       binop( Iop_Sar32, mkexpr(irt_regM), mkU8(16) ) ) );
9724ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9725ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        assign( irt_sum,
9726ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                binop( Iop_Add32,
9727ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       binop( Iop_Sar32, mkexpr(irt_regN), mkU8(16) ),
9728ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       binop( Iop_Sar32,
9729ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              binop( Iop_Shl32, mkexpr(irt_regM), mkU8(16) ),
9730ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              mkU8(16) ) ) );
9731ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9732ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        IRExpr* ire_result
9733ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          = binop( Iop_Or32,
9734ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   binop( Iop_Shl32, mkexpr(irt_sum), mkU8(16) ),
9735ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   binop( Iop_And32, mkexpr(irt_diff), mkU32(0xFFFF) ) );
9736ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9737ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        IRTemp ge10 = newTemp(Ity_I32);
9738ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        assign(ge10, unop(Iop_Not32, mkexpr(irt_diff)));
9739ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        put_GEFLAG32( 0, 31, mkexpr(ge10), condT );
9740ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        put_GEFLAG32( 1, 31, mkexpr(ge10), condT );
9741ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9742ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        IRTemp ge32 = newTemp(Ity_I32);
9743ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        assign(ge32, unop(Iop_Not32, mkexpr(irt_sum)));
9744ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        put_GEFLAG32( 2, 31, mkexpr(ge32), condT );
9745ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        put_GEFLAG32( 3, 31, mkexpr(ge32), condT );
9746ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9747ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (isT)
9748ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           putIRegT( regD, ire_result, condT );
9749ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        else
9750ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           putIRegA( regD, ire_result, condT, Ijk_Boring );
9751ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9752ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        DIP( "sasx%s r%u, r%u, r%u\n", nCC(conq), regD, regN, regM );
9753ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        return True;
9754ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     }
9755ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     /* fall through */
9756ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
9757ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9758ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* --------------- smuad, smuadx<c><Rd>,<Rn>,<Rm> --------------- */
9759ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* --------------- smsad, smsadx<c><Rd>,<Rn>,<Rm> --------------- */
9760ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   {
9761ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     UInt regD = 99, regN = 99, regM = 99, bitM = 99;
9762ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     Bool gate = False, isAD = False;
9763ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9764ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     if (isT) {
9765ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if ((INSNT0(15,4) == 0xFB2 || INSNT0(15,4) == 0xFB4)
9766ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            && (INSNT1(15,0) & 0xF0E0) == 0xF000) {
9767ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           regN = INSNT0(3,0);
9768ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           regD = INSNT1(11,8);
9769ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           regM = INSNT1(3,0);
9770ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           bitM = INSNT1(4,4);
9771ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           isAD = INSNT0(15,4) == 0xFB2;
9772ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
9773ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              gate = True;
9774ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
9775ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     } else {
9776ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (INSNA(27,20) == BITS8(0,1,1,1,0,0,0,0) &&
9777ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            INSNA(15,12) == BITS4(1,1,1,1)         &&
9778ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            (INSNA(7,4) & BITS4(1,0,0,1)) == BITS4(0,0,0,1) ) {
9779ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           regD = INSNA(19,16);
9780ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           regN = INSNA(3,0);
9781ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           regM = INSNA(11,8);
9782ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           bitM = INSNA(5,5);
9783ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           isAD = INSNA(6,6) == 0;
9784ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           if (regD != 15 && regN != 15 && regM != 15)
9785ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              gate = True;
9786ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
9787ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     }
9788ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9789ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     if (gate) {
9790ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        IRTemp irt_regN    = newTemp(Ity_I32);
9791ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        IRTemp irt_regM    = newTemp(Ity_I32);
9792ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        IRTemp irt_prod_lo = newTemp(Ity_I32);
9793ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        IRTemp irt_prod_hi = newTemp(Ity_I32);
9794ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        IRTemp tmpM        = newTemp(Ity_I32);
9795ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9796ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        assign( irt_regN, isT ? getIRegT(regN) : getIRegA(regN) );
9797ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9798ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        assign( tmpM, isT ? getIRegT(regM) : getIRegA(regM) );
9799ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        assign( irt_regM, genROR32(tmpM, (bitM & 1) ? 16 : 0) );
9800ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9801ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        assign( irt_prod_lo,
9802ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                binop( Iop_Mul32,
9803ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       binop( Iop_Sar32,
9804ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              binop(Iop_Shl32, mkexpr(irt_regN), mkU8(16)),
9805ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              mkU8(16) ),
9806ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       binop( Iop_Sar32,
9807ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              binop(Iop_Shl32, mkexpr(irt_regM), mkU8(16)),
9808ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              mkU8(16) ) ) );
9809ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        assign( irt_prod_hi, binop(Iop_Mul32,
9810ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                   binop(Iop_Sar32, mkexpr(irt_regN), mkU8(16)),
9811ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                   binop(Iop_Sar32, mkexpr(irt_regM), mkU8(16))) );
9812ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        IRExpr* ire_result
9813ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           = binop( isAD ? Iop_Add32 : Iop_Sub32,
9814ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    mkexpr(irt_prod_lo), mkexpr(irt_prod_hi) );
9815ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9816ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (isT)
9817ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           putIRegT( regD, ire_result, condT );
9818ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        else
9819ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           putIRegA( regD, ire_result, condT, Ijk_Boring );
9820ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9821ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (isAD) {
9822ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           or_into_QFLAG32(
9823ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              signed_overflow_after_Add32( ire_result,
9824ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                           irt_prod_lo, irt_prod_hi ),
9825ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              condT
9826ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           );
9827ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
9828ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9829ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        DIP("smu%cd%s%s r%u, r%u, r%u\n",
9830ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            isAD ? 'a' : 's',
9831ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            bitM ? "x" : "", nCC(conq), regD, regN, regM);
9832ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        return True;
9833ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     }
9834ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     /* fall through */
9835ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
9836ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9837ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* --------------- smlad{X}<c> <Rd>,<Rn>,<Rm>,<Ra> -------------- */
9838ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* --------------- smlsd{X}<c> <Rd>,<Rn>,<Rm>,<Ra> -------------- */
9839ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   {
9840ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     UInt regD = 99, regN = 99, regM = 99, regA = 99, bitM = 99;
9841ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     Bool gate = False, isAD = False;
9842ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9843ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     if (isT) {
9844ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       if ((INSNT0(15,4) == 0xFB2 || INSNT0(15,4) == 0xFB4)
9845ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           && INSNT1(7,5) == BITS3(0,0,0)) {
9846ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           regN = INSNT0(3,0);
9847ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           regD = INSNT1(11,8);
9848ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           regM = INSNT1(3,0);
9849ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           regA = INSNT1(15,12);
9850ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           bitM = INSNT1(4,4);
9851ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           isAD = INSNT0(15,4) == 0xFB2;
9852ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM)
9853ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               && !isBadRegT(regA))
9854ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              gate = True;
9855ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
9856ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     } else {
9857ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (INSNA(27,20) == BITS8(0,1,1,1,0,0,0,0) &&
9858ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            (INSNA(7,4) & BITS4(1,0,0,1)) == BITS4(0,0,0,1)) {
9859ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           regD = INSNA(19,16);
9860ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           regA = INSNA(15,12);
9861ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           regN = INSNA(3,0);
9862ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           regM = INSNA(11,8);
9863ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           bitM = INSNA(5,5);
9864ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           isAD = INSNA(6,6) == 0;
9865ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           if (regD != 15 && regN != 15 && regM != 15 && regA != 15)
9866ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              gate = True;
9867ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
9868ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     }
9869ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9870ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     if (gate) {
9871ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        IRTemp irt_regN    = newTemp(Ity_I32);
9872ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        IRTemp irt_regM    = newTemp(Ity_I32);
9873ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        IRTemp irt_regA    = newTemp(Ity_I32);
9874ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        IRTemp irt_prod_lo = newTemp(Ity_I32);
9875ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        IRTemp irt_prod_hi = newTemp(Ity_I32);
9876ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        IRTemp irt_sum     = newTemp(Ity_I32);
9877ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        IRTemp tmpM        = newTemp(Ity_I32);
9878ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9879ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        assign( irt_regN, isT ? getIRegT(regN) : getIRegA(regN) );
9880ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        assign( irt_regA, isT ? getIRegT(regA) : getIRegA(regA) );
9881ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9882ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        assign( tmpM, isT ? getIRegT(regM) : getIRegA(regM) );
9883ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        assign( irt_regM, genROR32(tmpM, (bitM & 1) ? 16 : 0) );
9884ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9885ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        assign( irt_prod_lo,
9886ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                binop(Iop_Mul32,
9887ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      binop(Iop_Sar32,
9888ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            binop( Iop_Shl32, mkexpr(irt_regN), mkU8(16) ),
9889ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            mkU8(16)),
9890ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      binop(Iop_Sar32,
9891ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            binop( Iop_Shl32, mkexpr(irt_regM), mkU8(16) ),
9892ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            mkU8(16))) );
9893ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        assign( irt_prod_hi,
9894ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                binop( Iop_Mul32,
9895ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       binop( Iop_Sar32, mkexpr(irt_regN), mkU8(16) ),
9896ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       binop( Iop_Sar32, mkexpr(irt_regM), mkU8(16) ) ) );
9897ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        assign( irt_sum, binop( isAD ? Iop_Add32 : Iop_Sub32,
9898ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                mkexpr(irt_prod_lo), mkexpr(irt_prod_hi) ) );
9899ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9900ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        IRExpr* ire_result = binop(Iop_Add32, mkexpr(irt_sum), mkexpr(irt_regA));
9901ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9902ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (isT)
9903ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           putIRegT( regD, ire_result, condT );
9904ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        else
9905ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           putIRegA( regD, ire_result, condT, Ijk_Boring );
9906ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9907ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (isAD) {
9908ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           or_into_QFLAG32(
9909ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              signed_overflow_after_Add32( mkexpr(irt_sum),
9910ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                           irt_prod_lo, irt_prod_hi ),
9911ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              condT
9912ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           );
9913ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
9914ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9915ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        or_into_QFLAG32(
9916ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           signed_overflow_after_Add32( ire_result, irt_sum, irt_regA ),
9917ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           condT
9918ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        );
9919ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9920ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        DIP("sml%cd%s%s r%u, r%u, r%u, r%u\n",
9921ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            isAD ? 'a' : 's',
9922ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            bitM ? "x" : "", nCC(conq), regD, regN, regM, regA);
9923ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        return True;
9924ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     }
9925ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     /* fall through */
9926ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
9927ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9928ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* ----- smlabb, smlabt, smlatb, smlatt <Rd>,<Rn>,<Rm>,<Ra> ----- */
9929ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   {
9930ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     UInt regD = 99, regN = 99, regM = 99, regA = 99, bitM = 99, bitN = 99;
9931ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     Bool gate = False;
9932ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9933ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     if (isT) {
9934ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (INSNT0(15,4) == 0xFB1 && INSNT1(7,6) == BITS2(0,0)) {
9935ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           regN = INSNT0(3,0);
9936ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           regD = INSNT1(11,8);
9937ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           regM = INSNT1(3,0);
9938ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           regA = INSNT1(15,12);
9939ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           bitM = INSNT1(4,4);
9940ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           bitN = INSNT1(5,5);
9941ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM)
9942ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               && !isBadRegT(regA))
9943ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              gate = True;
9944ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
9945ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     } else {
9946ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (INSNA(27,20) == BITS8(0,0,0,1,0,0,0,0) &&
9947ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            (INSNA(7,4) & BITS4(1,0,0,1)) == BITS4(1,0,0,0)) {
9948ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           regD = INSNA(19,16);
9949ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           regN = INSNA(3,0);
9950ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           regM = INSNA(11,8);
9951ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           regA = INSNA(15,12);
9952ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           bitM = INSNA(6,6);
9953ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           bitN = INSNA(5,5);
9954ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           if (regD != 15 && regN != 15 && regM != 15 && regA != 15)
9955ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              gate = True;
9956ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
9957ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     }
9958ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9959ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     if (gate) {
9960ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        IRTemp irt_regA = newTemp(Ity_I32);
9961ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        IRTemp irt_prod = newTemp(Ity_I32);
9962ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9963ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        assign( irt_prod,
9964ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                binop(Iop_Mul32,
9965ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      binop(Iop_Sar32,
9966ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            binop(Iop_Shl32,
9967ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                  isT ? getIRegT(regN) : getIRegA(regN),
9968ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                  mkU8(bitN ? 0 : 16)),
9969ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            mkU8(16)),
9970ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      binop(Iop_Sar32,
9971ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            binop(Iop_Shl32,
9972ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                  isT ? getIRegT(regM) : getIRegA(regM),
9973ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                  mkU8(bitM ? 0 : 16)),
9974ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            mkU8(16))) );
9975ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9976ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        assign( irt_regA, isT ? getIRegT(regA) : getIRegA(regA) );
9977ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9978ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        IRExpr* ire_result = binop(Iop_Add32, mkexpr(irt_prod), mkexpr(irt_regA));
9979ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9980ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (isT)
9981ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           putIRegT( regD, ire_result, condT );
9982ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        else
9983ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           putIRegA( regD, ire_result, condT, Ijk_Boring );
9984ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9985ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        or_into_QFLAG32(
9986ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           signed_overflow_after_Add32( ire_result, irt_prod, irt_regA ),
9987ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           condT
9988ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        );
9989ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9990ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        DIP( "smla%c%c%s r%u, r%u, r%u, r%u\n",
9991ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             bitN ? 't' : 'b', bitM ? 't' : 'b',
9992ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             nCC(conq), regD, regN, regM, regA );
9993ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        return True;
9994ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     }
9995ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     /* fall through */
9996ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
9997ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
9998ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* ----- smlawb, smlawt <Rd>,<Rn>,<Rm>,<Ra> ----- */
9999ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   {
10000ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     UInt regD = 99, regN = 99, regM = 99, regA = 99, bitM = 99;
10001ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     Bool gate = False;
10002ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10003ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     if (isT) {
10004ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (INSNT0(15,4) == 0xFB3 && INSNT1(7,5) == BITS3(0,0,0)) {
10005ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           regN = INSNT0(3,0);
10006ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           regD = INSNT1(11,8);
10007ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           regM = INSNT1(3,0);
10008ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           regA = INSNT1(15,12);
10009ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           bitM = INSNT1(4,4);
10010ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM)
10011ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               && !isBadRegT(regA))
10012ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              gate = True;
10013ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
10014ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     } else {
10015ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (INSNA(27,20) == BITS8(0,0,0,1,0,0,1,0) &&
10016ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            (INSNA(7,4) & BITS4(1,0,1,1)) == BITS4(1,0,0,0)) {
10017ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           regD = INSNA(19,16);
10018ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           regN = INSNA(3,0);
10019ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           regM = INSNA(11,8);
10020ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           regA = INSNA(15,12);
10021ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           bitM = INSNA(6,6);
10022ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           if (regD != 15 && regN != 15 && regM != 15 && regA != 15)
10023ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              gate = True;
10024ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
10025ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     }
10026ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10027ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     if (gate) {
10028ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        IRTemp irt_regA = newTemp(Ity_I32);
10029ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        IRTemp irt_prod = newTemp(Ity_I64);
10030ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10031ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        assign( irt_prod,
10032ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                binop(Iop_MullS32,
10033ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      isT ? getIRegT(regN) : getIRegA(regN),
10034ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      binop(Iop_Sar32,
10035ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            binop(Iop_Shl32,
10036ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                  isT ? getIRegT(regM) : getIRegA(regM),
10037ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                  mkU8(bitM ? 0 : 16)),
10038ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            mkU8(16))) );
10039ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10040ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        assign( irt_regA, isT ? getIRegT(regA) : getIRegA(regA) );
10041ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10042ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        IRTemp prod32 = newTemp(Ity_I32);
10043ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        assign(prod32,
10044ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               binop(Iop_Or32,
10045ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     binop(Iop_Shl32, unop(Iop_64HIto32, mkexpr(irt_prod)), mkU8(16)),
10046ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     binop(Iop_Shr32, unop(Iop_64to32, mkexpr(irt_prod)), mkU8(16))
10047ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        ));
10048ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10049ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        IRExpr* ire_result = binop(Iop_Add32, mkexpr(prod32), mkexpr(irt_regA));
10050ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10051ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (isT)
10052ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           putIRegT( regD, ire_result, condT );
10053ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        else
10054ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           putIRegA( regD, ire_result, condT, Ijk_Boring );
10055ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10056ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        or_into_QFLAG32(
10057ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           signed_overflow_after_Add32( ire_result, prod32, irt_regA ),
10058ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           condT
10059ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        );
10060ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10061ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        DIP( "smlaw%c%s r%u, r%u, r%u, r%u\n",
10062ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             bitM ? 't' : 'b',
10063ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             nCC(conq), regD, regN, regM, regA );
10064ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        return True;
10065ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     }
10066ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     /* fall through */
10067ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
10068ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10069ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* ------------------- sel<c> <Rd>,<Rn>,<Rm> -------------------- */
10070ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* fixme: fix up the test in v6media.c so that we can pass the ge
10071ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      flags as part of the test. */
10072ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   {
10073ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     UInt regD = 99, regN = 99, regM = 99;
10074ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     Bool gate = False;
10075ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10076ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     if (isT) {
10077ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (INSNT0(15,4) == 0xFAA && (INSNT1(15,0) & 0xF0F0) == 0xF080) {
10078ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           regN = INSNT0(3,0);
10079ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           regD = INSNT1(11,8);
10080ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           regM = INSNT1(3,0);
10081ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
10082ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              gate = True;
10083ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
10084ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     } else {
10085ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (INSNA(27,20) == BITS8(0,1,1,0,1,0,0,0) &&
10086ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            INSNA(11,8)  == BITS4(1,1,1,1)         &&
10087ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            INSNA(7,4)   == BITS4(1,0,1,1)) {
10088ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           regD = INSNA(15,12);
10089ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           regN = INSNA(19,16);
10090ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           regM = INSNA(3,0);
10091ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           if (regD != 15 && regN != 15 && regM != 15)
10092ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              gate = True;
10093ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
10094ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     }
10095ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10096ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     if (gate) {
10097ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        IRTemp irt_ge_flag0 = newTemp(Ity_I32);
10098ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        IRTemp irt_ge_flag1 = newTemp(Ity_I32);
10099ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        IRTemp irt_ge_flag2 = newTemp(Ity_I32);
10100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        IRTemp irt_ge_flag3 = newTemp(Ity_I32);
10101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        assign( irt_ge_flag0, get_GEFLAG32(0) );
10103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        assign( irt_ge_flag1, get_GEFLAG32(1) );
10104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        assign( irt_ge_flag2, get_GEFLAG32(2) );
10105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        assign( irt_ge_flag3, get_GEFLAG32(3) );
10106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        IRExpr* ire_ge_flag0_or
10108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          = binop(Iop_Or32, mkexpr(irt_ge_flag0),
10109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  binop(Iop_Sub32, mkU32(0), mkexpr(irt_ge_flag0)));
10110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        IRExpr* ire_ge_flag1_or
10111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          = binop(Iop_Or32, mkexpr(irt_ge_flag1),
10112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  binop(Iop_Sub32, mkU32(0), mkexpr(irt_ge_flag1)));
10113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        IRExpr* ire_ge_flag2_or
10114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          = binop(Iop_Or32, mkexpr(irt_ge_flag2),
10115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  binop(Iop_Sub32, mkU32(0), mkexpr(irt_ge_flag2)));
10116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        IRExpr* ire_ge_flag3_or
10117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          = binop(Iop_Or32, mkexpr(irt_ge_flag3),
10118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  binop(Iop_Sub32, mkU32(0), mkexpr(irt_ge_flag3)));
10119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        IRExpr* ire_ge_flags
10121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          = binop( Iop_Or32,
10122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   binop(Iop_Or32,
10123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         binop(Iop_And32,
10124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               binop(Iop_Sar32, ire_ge_flag0_or, mkU8(31)),
10125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               mkU32(0x000000ff)),
10126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         binop(Iop_And32,
10127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               binop(Iop_Sar32, ire_ge_flag1_or, mkU8(31)),
10128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               mkU32(0x0000ff00))),
10129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   binop(Iop_Or32,
10130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         binop(Iop_And32,
10131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               binop(Iop_Sar32, ire_ge_flag2_or, mkU8(31)),
10132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               mkU32(0x00ff0000)),
10133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         binop(Iop_And32,
10134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               binop(Iop_Sar32, ire_ge_flag3_or, mkU8(31)),
10135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               mkU32(0xff000000))) );
10136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        IRExpr* ire_result
10138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          = binop(Iop_Or32,
10139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  binop(Iop_And32,
10140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        isT ? getIRegT(regN) : getIRegA(regN),
10141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        ire_ge_flags ),
10142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  binop(Iop_And32,
10143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        isT ? getIRegT(regM) : getIRegA(regM),
10144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        unop(Iop_Not32, ire_ge_flags)));
10145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (isT)
10147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           putIRegT( regD, ire_result, condT );
10148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        else
10149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           putIRegA( regD, ire_result, condT, Ijk_Boring );
10150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        DIP("sel%s r%u, r%u, r%u\n", nCC(conq), regD, regN, regM );
10152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        return True;
10153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     }
10154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     /* fall through */
10155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
10156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* ----------------- uxtab16<c> Rd,Rn,Rm{,rot} ------------------ */
10158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   {
10159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     UInt regD = 99, regN = 99, regM = 99, rotate = 99;
10160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     Bool gate = False;
10161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     if (isT) {
10163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (INSNT0(15,4) == 0xFA3 && (INSNT1(15,0) & 0xF0C0) == 0xF080) {
10164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           regN   = INSNT0(3,0);
10165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           regD   = INSNT1(11,8);
10166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           regM   = INSNT1(3,0);
10167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           rotate = INSNT1(5,4);
10168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
10169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              gate = True;
10170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
10171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     } else {
10172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (INSNA(27,20) == BITS8(0,1,1,0,1,1,0,0) &&
10173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            INSNA(9,4)   == BITS6(0,0,0,1,1,1) ) {
10174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           regD   = INSNA(15,12);
10175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           regN   = INSNA(19,16);
10176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           regM   = INSNA(3,0);
10177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           rotate = INSNA(11,10);
10178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           if (regD != 15 && regN != 15 && regM != 15)
10179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             gate = True;
10180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
10181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     }
10182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     if (gate) {
10184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        IRTemp irt_regN = newTemp(Ity_I32);
10185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        assign( irt_regN, isT ? getIRegT(regN) : getIRegA(regN) );
10186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        IRTemp irt_regM = newTemp(Ity_I32);
10188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        assign( irt_regM, isT ? getIRegT(regM) : getIRegA(regM) );
10189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        IRTemp irt_rot = newTemp(Ity_I32);
10191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        assign( irt_rot, binop(Iop_And32,
10192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               genROR32(irt_regM, 8 * rotate),
10193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               mkU32(0x00FF00FF)) );
10194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        IRExpr* resLo
10196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           = binop(Iop_And32,
10197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   binop(Iop_Add32, mkexpr(irt_regN), mkexpr(irt_rot)),
10198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   mkU32(0x0000FFFF));
10199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        IRExpr* resHi
10201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           = binop(Iop_Add32,
10202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   binop(Iop_And32, mkexpr(irt_regN), mkU32(0xFFFF0000)),
10203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   binop(Iop_And32, mkexpr(irt_rot),  mkU32(0xFFFF0000)));
10204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        IRExpr* ire_result
10206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           = binop( Iop_Or32, resHi, resLo );
10207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (isT)
10209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           putIRegT( regD, ire_result, condT );
10210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        else
10211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           putIRegA( regD, ire_result, condT, Ijk_Boring );
10212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        DIP( "uxtab16%s r%u, r%u, r%u, ROR #%u\n",
10214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             nCC(conq), regD, regN, regM, 8 * rotate );
10215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        return True;
10216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     }
10217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     /* fall through */
10218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
10219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* --------------- usad8  Rd,Rn,Rm    ---------------- */
10221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* --------------- usada8 Rd,Rn,Rm,Ra ---------------- */
10222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   {
10223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     UInt rD = 99, rN = 99, rM = 99, rA = 99;
10224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     Bool gate = False;
10225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     if (isT) {
10227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       if (INSNT0(15,4) == 0xFB7 && INSNT1(7,4) == BITS4(0,0,0,0)) {
10228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           rN = INSNT0(3,0);
10229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           rA = INSNT1(15,12);
10230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           rD = INSNT1(11,8);
10231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           rM = INSNT1(3,0);
10232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           if (!isBadRegT(rD) && !isBadRegT(rN) && !isBadRegT(rM) && rA != 13)
10233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              gate = True;
10234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
10235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     } else {
10236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (INSNA(27,20) == BITS8(0,1,1,1,1,0,0,0) &&
10237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            INSNA(7,4)   == BITS4(0,0,0,1) ) {
10238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           rD = INSNA(19,16);
10239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           rA = INSNA(15,12);
10240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           rM = INSNA(11,8);
10241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           rN = INSNA(3,0);
10242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           if (rD != 15 && rN != 15 && rM != 15 /* but rA can be 15 */)
10243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              gate = True;
10244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
10245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     }
10246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     /* We allow rA == 15, to denote the usad8 (no accumulator) case. */
10247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     if (gate) {
10249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        IRExpr* rNe = isT ? getIRegT(rN) : getIRegA(rN);
10250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        IRExpr* rMe = isT ? getIRegT(rM) : getIRegA(rM);
10251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        IRExpr* rAe = rA == 15 ? mkU32(0)
10252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               : (isT ? getIRegT(rA) : getIRegA(rA));
10253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        IRExpr* res = binop(Iop_Add32,
10254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            binop(Iop_Sad8Ux4, rNe, rMe),
10255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            rAe);
10256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (isT)
10257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           putIRegT( rD, res, condT );
10258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        else
10259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           putIRegA( rD, res, condT, Ijk_Boring );
10260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (rA == 15) {
10262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           DIP( "usad8%s r%u, r%u, r%u\n",
10263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                nCC(conq), rD, rN, rM );
10264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        } else {
10265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           DIP( "usada8%s r%u, r%u, r%u, r%u\n",
10266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                nCC(conq), rD, rN, rM, rA );
10267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
10268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        return True;
10269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     }
10270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     /* fall through */
10271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
10272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10273663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* ------------------ qadd<c> <Rd>,<Rn>,<Rm> ------------------- */
10274663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   {
10275663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng     UInt regD = 99, regN = 99, regM = 99;
10276663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng     Bool gate = False;
10277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10278663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng     if (isT) {
10279663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        if (INSNT0(15,4) == 0xFA8 && (INSNT1(15,0) & 0xF0F0) == 0xF080) {
10280663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng           regN = INSNT0(3,0);
10281663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng           regD = INSNT1(11,8);
10282663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng           regM = INSNT1(3,0);
10283663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng           if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
10284663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng              gate = True;
10285663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        }
10286663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng     } else {
10287663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        if (INSNA(27,20) == BITS8(0,0,0,1,0,0,0,0) &&
10288663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            INSNA(11,8)  == BITS4(0,0,0,0)         &&
10289663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            INSNA(7,4)   == BITS4(0,1,0,1)) {
10290663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng           regD = INSNA(15,12);
10291663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng           regN = INSNA(19,16);
10292663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng           regM = INSNA(3,0);
10293663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng           if (regD != 15 && regN != 15 && regM != 15)
10294663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng              gate = True;
10295663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        }
10296663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng     }
10297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10298663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng     if (gate) {
10299663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        IRTemp rNt   = newTemp(Ity_I32);
10300663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        IRTemp rMt   = newTemp(Ity_I32);
10301663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        IRTemp res_q = newTemp(Ity_I32);
10302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10303663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) );
10304663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) );
10305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10306663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        assign(res_q, binop(Iop_QAdd32S, mkexpr(rMt), mkexpr(rNt)));
10307663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        if (isT)
10308663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng           putIRegT( regD, mkexpr(res_q), condT );
10309663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        else
10310663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng           putIRegA( regD, mkexpr(res_q), condT, Ijk_Boring );
10311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10312663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        or_into_QFLAG32(
10313663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng           signed_overflow_after_Add32(
10314663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng              binop(Iop_Add32, mkexpr(rMt), mkexpr(rNt)), rMt, rNt),
10315663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng           condT
10316663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        );
10317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10318663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        DIP("qadd%s r%u, r%u, r%u\n", nCC(conq),regD,regM,regN);
10319663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        return True;
10320663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng     }
10321663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng     /* fall through */
10322663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
10323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10324663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* ------------------ qdadd<c> <Rd>,<Rm>,<Rn> ------------------- */
10325663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   {
10326663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng     UInt regD = 99, regN = 99, regM = 99;
10327663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng     Bool gate = False;
10328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10329663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng     if (isT) {
10330663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        if (INSNT0(15,4) == 0xFA8 && (INSNT1(15,0) & 0xF0F0) == 0xF090) {
10331663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng           regN = INSNT0(3,0);
10332663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng           regD = INSNT1(11,8);
10333663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng           regM = INSNT1(3,0);
10334663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng           if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
10335663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng              gate = True;
10336663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        }
10337663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng     } else {
10338663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        if (INSNA(27,20) == BITS8(0,0,0,1,0,1,0,0) &&
10339663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            INSNA(11,8)  == BITS4(0,0,0,0)         &&
10340663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            INSNA(7,4)   == BITS4(0,1,0,1)) {
10341663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng           regD = INSNA(15,12);
10342663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng           regN = INSNA(19,16);
10343663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng           regM = INSNA(3,0);
10344663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng           if (regD != 15 && regN != 15 && regM != 15)
10345663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng              gate = True;
10346663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        }
10347663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng     }
10348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10349663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng     if (gate) {
10350663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        IRTemp rNt   = newTemp(Ity_I32);
10351663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        IRTemp rMt   = newTemp(Ity_I32);
10352663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        IRTemp rN_d  = newTemp(Ity_I32);
10353663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        IRTemp res_q = newTemp(Ity_I32);
10354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10355663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) );
10356663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) );
10357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10358663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        or_into_QFLAG32(
10359663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng           signed_overflow_after_Add32(
10360663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng              binop(Iop_Add32, mkexpr(rNt), mkexpr(rNt)), rNt, rNt),
10361663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng           condT
10362663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        );
10363663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
10364663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        assign(rN_d,  binop(Iop_QAdd32S, mkexpr(rNt), mkexpr(rNt)));
10365663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        assign(res_q, binop(Iop_QAdd32S, mkexpr(rMt), mkexpr(rN_d)));
10366663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        if (isT)
10367663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng           putIRegT( regD, mkexpr(res_q), condT );
10368663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        else
10369663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng           putIRegA( regD, mkexpr(res_q), condT, Ijk_Boring );
10370663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
10371663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        or_into_QFLAG32(
10372663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng           signed_overflow_after_Add32(
10373663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng              binop(Iop_Add32, mkexpr(rMt), mkexpr(rN_d)), rMt, rN_d),
10374663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng           condT
10375663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        );
10376663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
10377663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        DIP("qdadd%s r%u, r%u, r%u\n", nCC(conq),regD,regM,regN);
10378663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        return True;
10379663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng     }
10380663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng     /* fall through */
10381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
10382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10383663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* ------------------ qsub<c> <Rd>,<Rn>,<Rm> ------------------- */
10384663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   {
10385663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng     UInt regD = 99, regN = 99, regM = 99;
10386663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng     Bool gate = False;
10387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10388663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng     if (isT) {
10389663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        if (INSNT0(15,4) == 0xFA8 && (INSNT1(15,0) & 0xF0F0) == 0xF0A0) {
10390663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng           regN = INSNT0(3,0);
10391663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng           regD = INSNT1(11,8);
10392663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng           regM = INSNT1(3,0);
10393663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng           if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
10394663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng              gate = True;
10395663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        }
10396663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng     } else {
10397663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        if (INSNA(27,20) == BITS8(0,0,0,1,0,0,1,0) &&
10398663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            INSNA(11,8)  == BITS4(0,0,0,0)         &&
10399663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            INSNA(7,4)   == BITS4(0,1,0,1)) {
10400663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng           regD = INSNA(15,12);
10401663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng           regN = INSNA(19,16);
10402663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng           regM = INSNA(3,0);
10403663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng           if (regD != 15 && regN != 15 && regM != 15)
10404663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng              gate = True;
10405663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        }
10406663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng     }
10407663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
10408663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng     if (gate) {
10409663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        IRTemp rNt   = newTemp(Ity_I32);
10410663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        IRTemp rMt   = newTemp(Ity_I32);
10411663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        IRTemp res_q = newTemp(Ity_I32);
10412663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
10413663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) );
10414663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) );
10415663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
10416663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        assign(res_q, binop(Iop_QSub32S, mkexpr(rMt), mkexpr(rNt)));
10417663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        if (isT)
10418663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng           putIRegT( regD, mkexpr(res_q), condT );
10419663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        else
10420663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng           putIRegA( regD, mkexpr(res_q), condT, Ijk_Boring );
10421663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
10422663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        or_into_QFLAG32(
10423663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng           signed_overflow_after_Sub32(
10424663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng              binop(Iop_Sub32, mkexpr(rMt), mkexpr(rNt)), rMt, rNt),
10425663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng           condT
10426663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        );
10427663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
10428663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        DIP("qsub%s r%u, r%u, r%u\n", nCC(conq),regD,regM,regN);
10429663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        return True;
10430663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng     }
10431663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng     /* fall through */
10432663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
10433663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
10434663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* ------------------ qdsub<c> <Rd>,<Rm>,<Rn> ------------------- */
10435663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   {
10436663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng     UInt regD = 99, regN = 99, regM = 99;
10437663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng     Bool gate = False;
10438663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
10439663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng     if (isT) {
10440663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        if (INSNT0(15,4) == 0xFA8 && (INSNT1(15,0) & 0xF0F0) == 0xF0B0) {
10441663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng           regN = INSNT0(3,0);
10442663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng           regD = INSNT1(11,8);
10443663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng           regM = INSNT1(3,0);
10444663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng           if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
10445663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng              gate = True;
10446663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        }
10447663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng     } else {
10448663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        if (INSNA(27,20) == BITS8(0,0,0,1,0,1,1,0) &&
10449663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            INSNA(11,8)  == BITS4(0,0,0,0)         &&
10450663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            INSNA(7,4)   == BITS4(0,1,0,1)) {
10451663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng           regD = INSNA(15,12);
10452663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng           regN = INSNA(19,16);
10453663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng           regM = INSNA(3,0);
10454663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng           if (regD != 15 && regN != 15 && regM != 15)
10455663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng              gate = True;
10456663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        }
10457663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng     }
10458663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
10459663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng     if (gate) {
10460663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        IRTemp rNt   = newTemp(Ity_I32);
10461663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        IRTemp rMt   = newTemp(Ity_I32);
10462663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        IRTemp rN_d  = newTemp(Ity_I32);
10463663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        IRTemp res_q = newTemp(Ity_I32);
10464663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
10465663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) );
10466663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) );
10467663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
10468663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        or_into_QFLAG32(
10469663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng           signed_overflow_after_Add32(
10470663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng              binop(Iop_Add32, mkexpr(rNt), mkexpr(rNt)), rNt, rNt),
10471663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng           condT
10472663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        );
10473663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
10474663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        assign(rN_d,  binop(Iop_QAdd32S, mkexpr(rNt), mkexpr(rNt)));
10475663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        assign(res_q, binop(Iop_QSub32S, mkexpr(rMt), mkexpr(rN_d)));
10476663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        if (isT)
10477663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng           putIRegT( regD, mkexpr(res_q), condT );
10478663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        else
10479663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng           putIRegA( regD, mkexpr(res_q), condT, Ijk_Boring );
10480663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
10481663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        or_into_QFLAG32(
10482663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng           signed_overflow_after_Sub32(
10483663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng              binop(Iop_Sub32, mkexpr(rMt), mkexpr(rN_d)), rMt, rN_d),
10484663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng           condT
10485663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        );
10486663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
10487663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        DIP("qdsub%s r%u, r%u, r%u\n", nCC(conq),regD,regM,regN);
10488663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        return True;
10489663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng     }
10490663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng     /* fall through */
10491663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
10492663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
10493663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* ------------------ uqsub16<c> <Rd>,<Rn>,<Rm> ------------------ */
10494663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   {
10495663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng     UInt regD = 99, regN = 99, regM = 99;
10496663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng     Bool gate = False;
10497663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
10498663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng     if (isT) {
10499663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        if (INSNT0(15,4) == 0xFAD && (INSNT1(15,0) & 0xF0F0) == 0xF050) {
10500663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng           regN = INSNT0(3,0);
10501663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng           regD = INSNT1(11,8);
10502663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng           regM = INSNT1(3,0);
10503663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng           if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
10504663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng              gate = True;
10505663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        }
10506663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng     } else {
10507663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        if (INSNA(27,20) == BITS8(0,1,1,0,0,1,1,0) &&
10508663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            INSNA(11,8)  == BITS4(1,1,1,1)         &&
10509663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            INSNA(7,4)   == BITS4(0,1,1,1)) {
10510663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng           regD = INSNA(15,12);
10511663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng           regN = INSNA(19,16);
10512663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng           regM = INSNA(3,0);
10513663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng           if (regD != 15 && regN != 15 && regM != 15)
10514663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng             gate = True;
10515663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        }
10516663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng     }
10517663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
10518663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng     if (gate) {
10519663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        IRTemp rNt   = newTemp(Ity_I32);
10520663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        IRTemp rMt   = newTemp(Ity_I32);
10521663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        IRTemp res_q = newTemp(Ity_I32);
10522663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
10523663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) );
10524663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) );
10525663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
10526663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        assign(res_q, binop(Iop_QSub16Ux2, mkexpr(rNt), mkexpr(rMt)));
10527663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        if (isT)
10528663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng           putIRegT( regD, mkexpr(res_q), condT );
10529663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        else
10530663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng           putIRegA( regD, mkexpr(res_q), condT, Ijk_Boring );
10531663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
10532663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        DIP("uqsub16%s r%u, r%u, r%u\n", nCC(conq),regD,regN,regM);
10533663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        return True;
10534663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng     }
10535663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng     /* fall through */
10536663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
10537663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
10538663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* ----------------- shadd16<c> <Rd>,<Rn>,<Rm> ------------------- */
10539663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   {
10540663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng     UInt regD = 99, regN = 99, regM = 99;
10541663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng     Bool gate = False;
10542663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
10543663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng     if (isT) {
10544663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        if (INSNT0(15,4) == 0xFA9 && (INSNT1(15,0) & 0xF0F0) == 0xF020) {
10545663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng           regN = INSNT0(3,0);
10546663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng           regD = INSNT1(11,8);
10547663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng           regM = INSNT1(3,0);
10548663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng           if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
10549663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng              gate = True;
10550663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        }
10551663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng     } else {
10552663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        if (INSNA(27,20) == BITS8(0,1,1,0,0,0,1,1) &&
10553663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            INSNA(11,8)  == BITS4(1,1,1,1)         &&
10554663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            INSNA(7,4)   == BITS4(0,0,0,1)) {
10555663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng           regD = INSNA(15,12);
10556663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng           regN = INSNA(19,16);
10557663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng           regM = INSNA(3,0);
10558663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng           if (regD != 15 && regN != 15 && regM != 15)
10559663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng              gate = True;
10560663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        }
10561663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng     }
10562663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
10563663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng     if (gate) {
10564663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        IRTemp rNt   = newTemp(Ity_I32);
10565663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        IRTemp rMt   = newTemp(Ity_I32);
10566663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        IRTemp res_q = newTemp(Ity_I32);
10567663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
10568663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) );
10569663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) );
10570663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
10571663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        assign(res_q, binop(Iop_HAdd16Sx2, mkexpr(rNt), mkexpr(rMt)));
10572663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        if (isT)
10573663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng           putIRegT( regD, mkexpr(res_q), condT );
10574663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        else
10575663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng           putIRegA( regD, mkexpr(res_q), condT, Ijk_Boring );
10576663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
10577663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        DIP("shadd16%s r%u, r%u, r%u\n", nCC(conq),regD,regN,regM);
10578663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        return True;
10579663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng     }
10580663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng     /* fall through */
10581663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
10582663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
10583663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* ----------------- uhsub8<c> <Rd>,<Rn>,<Rm> ------------------- */
10584663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   {
10585663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng     UInt regD = 99, regN = 99, regM = 99;
10586663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng     Bool gate = False;
10587663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
10588663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng     if (isT) {
10589663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        if (INSNT0(15,4) == 0xFAC && (INSNT1(15,0) & 0xF0F0) == 0xF060) {
10590663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng           regN = INSNT0(3,0);
10591663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng           regD = INSNT1(11,8);
10592663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng           regM = INSNT1(3,0);
10593663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng           if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
10594663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng              gate = True;
10595663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        }
10596663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng     } else {
10597663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        if (INSNA(27,20) == BITS8(0,1,1,0,0,1,1,1) &&
10598663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            INSNA(11,8)  == BITS4(1,1,1,1)         &&
10599663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            INSNA(7,4)   == BITS4(1,1,1,1)) {
10600663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng           regD = INSNA(15,12);
10601663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng           regN = INSNA(19,16);
10602663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng           regM = INSNA(3,0);
10603663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng           if (regD != 15 && regN != 15 && regM != 15)
10604663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng              gate = True;
10605663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        }
10606663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng     }
10607663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
10608663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng     if (gate) {
10609663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        IRTemp rNt   = newTemp(Ity_I32);
10610663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        IRTemp rMt   = newTemp(Ity_I32);
10611663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        IRTemp res_q = newTemp(Ity_I32);
10612663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
10613663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) );
10614663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) );
10615663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
10616663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        assign(res_q, binop(Iop_HSub8Ux4, mkexpr(rNt), mkexpr(rMt)));
10617663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        if (isT)
10618663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng           putIRegT( regD, mkexpr(res_q), condT );
10619663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        else
10620663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng           putIRegA( regD, mkexpr(res_q), condT, Ijk_Boring );
10621663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
10622663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        DIP("uhsub8%s r%u, r%u, r%u\n", nCC(conq),regD,regN,regM);
10623663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        return True;
10624663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng     }
10625663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng     /* fall through */
10626663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
10627663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
10628663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* ----------------- uhsub16<c> <Rd>,<Rn>,<Rm> ------------------- */
10629663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   {
10630663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng     UInt regD = 99, regN = 99, regM = 99;
10631663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng     Bool gate = False;
10632663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
10633663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng     if (isT) {
10634663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        if (INSNT0(15,4) == 0xFAD && (INSNT1(15,0) & 0xF0F0) == 0xF060) {
10635663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng           regN = INSNT0(3,0);
10636663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng           regD = INSNT1(11,8);
10637663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng           regM = INSNT1(3,0);
10638663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng           if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
10639663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng              gate = True;
10640663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        }
10641663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng     } else {
10642663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        if (INSNA(27,20) == BITS8(0,1,1,0,0,1,1,1) &&
10643663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            INSNA(11,8)  == BITS4(1,1,1,1)         &&
10644663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            INSNA(7,4)   == BITS4(0,1,1,1)) {
10645663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng           regD = INSNA(15,12);
10646663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng           regN = INSNA(19,16);
10647663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng           regM = INSNA(3,0);
10648663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng           if (regD != 15 && regN != 15 && regM != 15)
10649663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng              gate = True;
10650663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        }
10651663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng     }
10652663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
10653663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng     if (gate) {
10654663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        IRTemp rNt   = newTemp(Ity_I32);
10655663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        IRTemp rMt   = newTemp(Ity_I32);
10656663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        IRTemp res_q = newTemp(Ity_I32);
10657663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
10658663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) );
10659663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) );
10660663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
10661663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        assign(res_q, binop(Iop_HSub16Ux2, mkexpr(rNt), mkexpr(rMt)));
10662663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        if (isT)
10663663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng           putIRegT( regD, mkexpr(res_q), condT );
10664663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        else
10665663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng           putIRegA( regD, mkexpr(res_q), condT, Ijk_Boring );
10666663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
10667663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        DIP("uhsub16%s r%u, r%u, r%u\n", nCC(conq),regD,regN,regM);
10668663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        return True;
10669663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng     }
10670663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng     /* fall through */
10671663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
10672663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
10673663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* ---------- Doesn't match anything. ---------- */
10674663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return False;
10675663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
10676663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#  undef INSNA
10677663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#  undef INSNT0
10678663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#  undef INSNT1
10679663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
10680663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
10681663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
10682663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/*------------------------------------------------------------*/
10683663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/*--- LDMxx/STMxx helper (both ARM and Thumb32)            ---*/
10684663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/*------------------------------------------------------------*/
10685663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
10686663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* Generate IR for LDMxx and STMxx.  This is complex.  Assumes it's
10687663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   unconditional, so the caller must produce a jump-around before
10688663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   calling this, if the insn is to be conditional.  Caller is
10689663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   responsible for all validation of parameters.  For LDMxx, if PC is
10690663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   amongst the values loaded, caller is also responsible for
10691663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   generating the jump. */
10692663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic void mk_ldm_stm ( Bool arm,     /* True: ARM, False: Thumb */
10693663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                         UInt rN,      /* base reg */
10694663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                         UInt bINC,    /* 1: inc,  0: dec */
10695663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                         UInt bBEFORE, /* 1: inc/dec before, 0: after */
10696663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                         UInt bW,      /* 1: writeback to Rn */
10697663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                         UInt bL,      /* 1: load, 0: store */
10698663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                         UInt regList )
10699663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
10700663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   Int i, r, m, nRegs;
10701663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp jk = Ijk_Boring;
10702663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
10703663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* Get hold of the old Rn value.  We might need to write its value
10704663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      to memory during a store, and if it's also the writeback
10705663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      register then we need to get its value now.  We can't treat it
10706663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      exactly like the other registers we're going to transfer,
10707663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      because for xxMDA and xxMDB writeback forms, the generated IR
10708663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      updates Rn in the guest state before any transfers take place.
10709663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      We have to do this as per comments below, in order that if Rn is
10710663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      the stack pointer then it always has a value is below or equal
10711663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      to any of the transfer addresses.  Ick. */
10712663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp oldRnT = newTemp(Ity_I32);
10713663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign(oldRnT, arm ? getIRegA(rN) : getIRegT(rN));
10714663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
10715663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp anchorT = newTemp(Ity_I32);
10716663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* The old (Addison-Wesley) ARM ARM seems to say that LDMxx/STMxx
10717663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      ignore the bottom two bits of the address.  However, Cortex-A8
10718663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      doesn't seem to care.  Hence: */
10719663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* No .. don't force alignment .. */
10720663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* assign(anchorT, binop(Iop_And32, mkexpr(oldRnT), mkU32(~3U))); */
10721663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* Instead, use the potentially misaligned address directly. */
10722663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   assign(anchorT, mkexpr(oldRnT));
10723663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
10724663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IROp opADDorSUB = bINC ? Iop_Add32 : Iop_Sub32;
10725663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   // bINC == 1:  xxMIA, xxMIB
10726663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   // bINC == 0:  xxMDA, xxMDB
10727663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
10728663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   // For xxMDA and xxMDB, update Rn first if necessary.  We have
10729663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   // to do this first so that, for the common idiom of the transfers
10730663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   // faulting because we're pushing stuff onto a stack and the stack
10731663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   // is growing down onto allocate-on-fault pages (as Valgrind simulates),
10732663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   // we need to have the SP up-to-date "covering" (pointing below) the
10733663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   // transfer area.  For the same reason, if we are doing xxMIA or xxMIB,
10734663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   // do the transfer first, and then update rN afterwards.
10735663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   nRegs = 0;
10736663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   for (i = 0; i < 16; i++) {
10737663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng     if ((regList & (1 << i)) != 0)
10738663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         nRegs++;
10739663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
10740663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (bW == 1 && !bINC) {
10741663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      IRExpr* e = binop(opADDorSUB, mkexpr(oldRnT), mkU32(4*nRegs));
10742663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (arm)
10743663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         putIRegA( rN, e, IRTemp_INVALID, Ijk_Boring );
10744663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      else
10745663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         putIRegT( rN, e, IRTemp_INVALID );
10746663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
10747663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
10748663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   // Make up a list of the registers to transfer, and their offsets
10749663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   // in memory relative to the anchor.  If the base reg (Rn) is part
10750663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   // of the transfer, then do it last for a load and first for a store.
10751663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UInt xReg[16], xOff[16];
10752663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   Int  nX = 0;
10753663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   m = 0;
10754663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   for (i = 0; i < 16; i++) {
10755663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      r = bINC ? i : (15-i);
10756663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (0 == (regList & (1<<r)))
10757663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         continue;
10758663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (bBEFORE)
10759663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         m++;
10760663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* paranoia: check we aren't transferring the writeback
10761663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         register during a load. Should be assured by decode-point
10762663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         check above. */
10763663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (bW == 1 && bL == 1)
10764663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         vassert(r != rN);
10765663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
10766663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      xOff[nX] = 4 * m;
10767663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      xReg[nX] = r;
10768663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      nX++;
10769663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
10770663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (!bBEFORE)
10771663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         m++;
10772663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
10773663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vassert(m == nRegs);
10774663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vassert(nX == nRegs);
10775663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vassert(nX <= 16);
10776663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
10777663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (bW == 0 && (regList & (1<<rN)) != 0) {
10778663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* Non-writeback, and basereg is to be transferred.  Do its
10779663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         transfer last for a load and first for a store.  Requires
10780663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         reordering xOff/xReg. */
10781663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (0) {
10782663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         vex_printf("\nREG_LIST_PRE: (rN=%d)\n", rN);
10783663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         for (i = 0; i < nX; i++)
10784663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            vex_printf("reg %d   off %d\n", xReg[i], xOff[i]);
10785663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         vex_printf("\n");
10786663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
10787663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
10788663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      vassert(nX > 0);
10789663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      for (i = 0; i < nX; i++) {
10790663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (xReg[i] == rN)
10791663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng             break;
10792663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
10793663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      vassert(i < nX); /* else we didn't find it! */
10794663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      UInt tReg = xReg[i];
10795663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      UInt tOff = xOff[i];
10796663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (bL == 1) {
10797663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* load; make this transfer happen last */
10798663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (i < nX-1) {
10799663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            for (m = i+1; m < nX; m++) {
10800663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               xReg[m-1] = xReg[m];
10801663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               xOff[m-1] = xOff[m];
10802663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            }
10803663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            vassert(m == nX);
10804663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            xReg[m-1] = tReg;
10805663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            xOff[m-1] = tOff;
10806663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
10807663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      } else {
10808663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* store; make this transfer happen first */
10809663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (i > 0) {
10810ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            for (m = i-1; m >= 0; m--) {
10811ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               xReg[m+1] = xReg[m];
10812ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               xOff[m+1] = xOff[m];
10813ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
10814ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vassert(m == -1);
10815ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            xReg[0] = tReg;
10816ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            xOff[0] = tOff;
10817ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
10818ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
10819ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10820ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (0) {
10821ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("REG_LIST_POST:\n");
10822ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         for (i = 0; i < nX; i++)
10823ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vex_printf("reg %d   off %d\n", xReg[i], xOff[i]);
10824ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("\n");
10825ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
10826ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
10827ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10828b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   /* According to the Cortex A8 TRM Sec. 5.2.1, LDM(1) with r13 as the base
10829b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov       register and PC in the register list is a return for purposes of branch
10830b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov       prediction.
10831b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      The ARM ARM Sec. C9.10.1 further specifies that writeback must be enabled
10832b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov       to be counted in event 0x0E (Procedure return).*/
10833b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   if (rN == 13 && bL == 1 && bINC && !bBEFORE && bW == 1) {
10834b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      jk = Ijk_Ret;
10835b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   }
10836b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
10837ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Actually generate the transfers */
10838ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (i = 0; i < nX; i++) {
10839ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      r = xReg[i];
10840ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (bL == 1) {
10841ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRExpr* e = loadLE(Ity_I32,
10842ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            binop(opADDorSUB, mkexpr(anchorT),
10843ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                  mkU32(xOff[i])));
10844ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (arm) {
10845b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            putIRegA( r, e, IRTemp_INVALID, jk );
10846ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
10847ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            // no: putIRegT( r, e, IRTemp_INVALID );
10848ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            // putIRegT refuses to write to R15.  But that might happen.
10849ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            // Since this is uncond, and we need to be able to
10850ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            // write the PC, just use the low level put:
10851ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            llPutIReg( r, e );
10852ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
10853ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else {
10854ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* if we're storing Rn, make sure we use the correct
10855ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            value, as per extensive comments above */
10856ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         storeLE( binop(opADDorSUB, mkexpr(anchorT), mkU32(xOff[i])),
10857ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  r == rN ? mkexpr(oldRnT)
10858ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          : (arm ? getIRegA(r) : getIRegT(r) ) );
10859ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
10860ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
10861ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10862ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // If we are doing xxMIA or xxMIB,
10863ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // do the transfer first, and then update rN afterwards.
10864ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (bW == 1 && bINC) {
10865ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRExpr* e = binop(opADDorSUB, mkexpr(oldRnT), mkU32(4*nRegs));
10866ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (arm)
10867ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putIRegA( rN, e, IRTemp_INVALID, Ijk_Boring );
10868ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      else
10869ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putIRegT( rN, e, IRTemp_INVALID );
10870ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
10871ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
10872ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10873ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10874ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
10875ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- VFP (CP 10 and 11) instructions                      ---*/
10876ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
10877ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10878ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Both ARM and Thumb */
10879ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10880ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Translate a CP10 or CP11 instruction.  If successful, returns
10881ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   True and *dres may or may not be updated.  If failure, returns
10882ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   False and doesn't change *dres nor create any IR.
10883ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10884ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   The ARM and Thumb encodings are identical for the low 28 bits of
10885ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   the insn (yay!) and that's what the caller must supply, iow, imm28
10886ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   has the top 4 bits masked out.  Caller is responsible for
10887ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   determining whether the masked-out bits are valid for a CP10/11
10888ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   insn.  The rules for the top 4 bits are:
10889ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10890ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     ARM: 0000 to 1110 allowed, and this is the gating condition.
10891ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     1111 (NV) is not allowed.
10892ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10893ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     Thumb: must be 1110.  The gating condition is taken from
10894ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     ITSTATE in the normal way.
10895ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10896ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Conditionalisation:
10897ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10898ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Caller must supply an IRTemp 'condT' holding the gating condition,
10899ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   or IRTemp_INVALID indicating the insn is always executed.
10900ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10901ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Caller must also supply an ARMCondcode 'cond'.  This is only used
10902ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for debug printing, no other purpose.  For ARM, this is simply the
10903ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   top 4 bits of the original instruction.  For Thumb, the condition
10904ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   is not (really) known until run time, and so ARMCondAL should be
10905ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   passed, only so that printing of these instructions does not show
10906ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   any condition.
10907ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10908ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Finally, the caller must indicate whether this occurs in ARM or
10909ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Thumb code.
10910ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
10911ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool decode_CP10_CP11_instruction (
10912ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               /*MOD*/DisResult* dres,
10913ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               UInt              insn28,
10914ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               IRTemp            condT,
10915ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               ARMCondcode       conq,
10916ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               Bool              isT
10917ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            )
10918ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
10919ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  define INSN(_bMax,_bMin)  SLICE_UInt(insn28, (_bMax), (_bMin))
10920ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10921ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(INSN(31,28) == BITS4(0,0,0,0)); // caller's obligation
10922ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10923ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (isT) {
10924ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert(conq == ARMCondAL);
10925ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
10926ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert(conq >= ARMCondEQ && conq <= ARMCondAL);
10927ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
10928ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10929ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* ----------------------------------------------------------- */
10930ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* -- VFP instructions -- double precision (mostly)         -- */
10931ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* ----------------------------------------------------------- */
10932ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10933ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* --------------------- fldmx, fstmx --------------------- */
10934ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /*
10935ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                 31   27   23   19 15 11   7   0
10936ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                         P U WL
10937ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      C4-100, C5-26  1  FSTMX    cond 1100 1000 Rn Dd 1011 offset
10938ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      C4-100, C5-28  2  FSTMIAX  cond 1100 1010 Rn Dd 1011 offset
10939ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      C4-100, C5-30  3  FSTMDBX  cond 1101 0010 Rn Dd 1011 offset
10940ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10941ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      C4-42, C5-26   1  FLDMX    cond 1100 1001 Rn Dd 1011 offset
10942ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      C4-42, C5-28   2  FLDMIAX  cond 1100 1011 Rn Dd 1011 offset
10943ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      C4-42, C5-30   3  FLDMDBX  cond 1101 0011 Rn Dd 1011 offset
10944ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10945ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Regs transferred: Dd .. D(d + (offset-3)/2)
10946ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      offset must be odd, must not imply a reg > 15
10947ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IA/DB: Rn is changed by (4 + 8 x # regs transferred)
10948ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10949ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case coding:
10950ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         1  at-Rn   (access at Rn)
10951ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         2  ia-Rn   (access at Rn, then Rn += 4+8n)
10952ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         3  db-Rn   (Rn -= 4+8n,   then access at Rn)
10953ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   */
10954ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (BITS8(1,1,0,0,0,0,0,0) == (INSN(27,20) & BITS8(1,1,1,0,0,0,0,0))
10955ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && INSN(11,8) == BITS4(1,0,1,1)) {
10956ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt bP      = (insn28 >> 24) & 1;
10957ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt bU      = (insn28 >> 23) & 1;
10958ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt bW      = (insn28 >> 21) & 1;
10959ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt bL      = (insn28 >> 20) & 1;
10960ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt offset  = (insn28 >> 0) & 0xFF;
10961ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt rN      = INSN(19,16);
10962ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt dD      = (INSN(22,22) << 4) | INSN(15,12);
10963ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt nRegs   = (offset - 1) / 2;
10964ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt summary = 0;
10965ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Int  i;
10966ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10967ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /**/ if (bP == 0 && bU == 1 && bW == 0) {
10968ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         summary = 1;
10969ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
10970ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      else if (bP == 0 && bU == 1 && bW == 1) {
10971ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         summary = 2;
10972ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
10973ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      else if (bP == 1 && bU == 0 && bW == 1) {
10974ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         summary = 3;
10975ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
10976ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      else goto after_vfp_fldmx_fstmx;
10977ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10978ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* no writebacks to r15 allowed.  No use of r15 in thumb mode. */
10979ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (rN == 15 && (summary == 2 || summary == 3 || isT))
10980ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto after_vfp_fldmx_fstmx;
10981ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10982ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* offset must be odd, and specify at least one register */
10983ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (0 == (offset & 1) || offset < 3)
10984ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto after_vfp_fldmx_fstmx;
10985ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10986ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* can't transfer regs after D15 */
10987ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (dD + nRegs - 1 >= 32)
10988ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto after_vfp_fldmx_fstmx;
10989ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10990ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Now, we can't do a conditional load or store, since that very
10991ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         likely will generate an exception.  So we have to take a side
10992ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         exit at this point if the condition is false. */
10993ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (condT != IRTemp_INVALID) {
10994ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (isT)
10995ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            mk_skip_over_T32_if_cond_is_false( condT );
10996ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         else
10997ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            mk_skip_over_A32_if_cond_is_false( condT );
10998ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         condT = IRTemp_INVALID;
10999ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
11000ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Ok, now we're unconditional.  Do the load or store. */
11001ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11002ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* get the old Rn value */
11003ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp rnT = newTemp(Ity_I32);
11004ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign(rnT, align4if(isT ? getIRegT(rN) : getIRegA(rN),
11005ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           rN == 15));
11006ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11007ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* make a new value for Rn, post-insn */
11008ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp rnTnew = IRTemp_INVALID;
11009ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (summary == 2 || summary == 3) {
11010ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         rnTnew = newTemp(Ity_I32);
11011ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign(rnTnew, binop(summary == 2 ? Iop_Add32 : Iop_Sub32,
11012ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              mkexpr(rnT),
11013ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              mkU32(4 + 8 * nRegs)));
11014ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
11015ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11016ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* decide on the base transfer address */
11017ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp taT = newTemp(Ity_I32);
11018ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign(taT,  summary == 3 ? mkexpr(rnTnew) : mkexpr(rnT));
11019ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11020ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* update Rn if necessary -- in case 3, we're moving it down, so
11021ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         update before any memory reference, in order to keep Memcheck
11022ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         and V's stack-extending logic (on linux) happy */
11023ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (summary == 3) {
11024ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (isT)
11025ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            putIRegT(rN, mkexpr(rnTnew), IRTemp_INVALID);
11026ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         else
11027ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            putIRegA(rN, mkexpr(rnTnew), IRTemp_INVALID, Ijk_Boring);
11028ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
11029ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11030ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* generate the transfers */
11031ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      for (i = 0; i < nRegs; i++) {
11032ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRExpr* addr = binop(Iop_Add32, mkexpr(taT), mkU32(8*i));
11033ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (bL) {
11034ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            putDReg(dD + i, loadLE(Ity_F64, addr), IRTemp_INVALID);
11035ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
11036ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            storeLE(addr, getDReg(dD + i));
11037ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
11038ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
11039ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11040ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* update Rn if necessary -- in case 2, we're moving it up, so
11041ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         update after any memory reference, in order to keep Memcheck
11042ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         and V's stack-extending logic (on linux) happy */
11043ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (summary == 2) {
11044ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (isT)
11045ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            putIRegT(rN, mkexpr(rnTnew), IRTemp_INVALID);
11046ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         else
11047ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            putIRegA(rN, mkexpr(rnTnew), IRTemp_INVALID, Ijk_Boring);
11048ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
11049ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11050ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HChar* nm = bL==1 ? "ld" : "st";
11051ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch (summary) {
11052ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case 1:  DIP("f%smx%s r%u, {d%u-d%u}\n",
11053ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      nm, nCC(conq), rN, dD, dD + nRegs - 1);
11054ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  break;
11055ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case 2:  DIP("f%smiax%s r%u!, {d%u-d%u}\n",
11056ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      nm, nCC(conq), rN, dD, dD + nRegs - 1);
11057ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  break;
11058ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case 3:  DIP("f%smdbx%s r%u!, {d%u-d%u}\n",
11059ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      nm, nCC(conq), rN, dD, dD + nRegs - 1);
11060ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  break;
11061ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         default: vassert(0);
11062ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
11063ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11064ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      goto decode_success_vfp;
11065ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* FIXME alignment constraints? */
11066ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
11067ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11068ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  after_vfp_fldmx_fstmx:
11069ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11070ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* --------------------- fldmd, fstmd --------------------- */
11071ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /*
11072ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                 31   27   23   19 15 11   7   0
11073ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                         P U WL
11074ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      C4-96, C5-26   1  FSTMD    cond 1100 1000 Rn Dd 1011 offset
11075ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      C4-96, C5-28   2  FSTMDIA  cond 1100 1010 Rn Dd 1011 offset
11076ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      C4-96, C5-30   3  FSTMDDB  cond 1101 0010 Rn Dd 1011 offset
11077ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11078ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      C4-38, C5-26   1  FLDMD    cond 1100 1001 Rn Dd 1011 offset
11079ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      C4-38, C5-28   2  FLDMIAD  cond 1100 1011 Rn Dd 1011 offset
11080ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      C4-38, C5-30   3  FLDMDBD  cond 1101 0011 Rn Dd 1011 offset
11081ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11082ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Regs transferred: Dd .. D(d + (offset-2)/2)
11083ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      offset must be even, must not imply a reg > 15
11084ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IA/DB: Rn is changed by (8 x # regs transferred)
11085ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11086ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case coding:
11087ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         1  at-Rn   (access at Rn)
11088ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         2  ia-Rn   (access at Rn, then Rn += 8n)
11089ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         3  db-Rn   (Rn -= 8n,     then access at Rn)
11090ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   */
11091ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (BITS8(1,1,0,0,0,0,0,0) == (INSN(27,20) & BITS8(1,1,1,0,0,0,0,0))
11092ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && INSN(11,8) == BITS4(1,0,1,1)) {
11093ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt bP      = (insn28 >> 24) & 1;
11094ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt bU      = (insn28 >> 23) & 1;
11095ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt bW      = (insn28 >> 21) & 1;
11096ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt bL      = (insn28 >> 20) & 1;
11097ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt offset  = (insn28 >> 0) & 0xFF;
11098ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt rN      = INSN(19,16);
11099ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt dD      = (INSN(22,22) << 4) | INSN(15,12);
11100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt nRegs   = offset / 2;
11101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt summary = 0;
11102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Int  i;
11103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /**/ if (bP == 0 && bU == 1 && bW == 0) {
11105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         summary = 1;
11106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
11107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      else if (bP == 0 && bU == 1 && bW == 1) {
11108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         summary = 2;
11109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
11110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      else if (bP == 1 && bU == 0 && bW == 1) {
11111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         summary = 3;
11112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
11113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      else goto after_vfp_fldmd_fstmd;
11114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* no writebacks to r15 allowed.  No use of r15 in thumb mode. */
11116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (rN == 15 && (summary == 2 || summary == 3 || isT))
11117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto after_vfp_fldmd_fstmd;
11118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* offset must be even, and specify at least one register */
11120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (1 == (offset & 1) || offset < 2)
11121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto after_vfp_fldmd_fstmd;
11122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* can't transfer regs after D15 */
11124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (dD + nRegs - 1 >= 32)
11125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto after_vfp_fldmd_fstmd;
11126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Now, we can't do a conditional load or store, since that very
11128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         likely will generate an exception.  So we have to take a side
11129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         exit at this point if the condition is false. */
11130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (condT != IRTemp_INVALID) {
11131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (isT)
11132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            mk_skip_over_T32_if_cond_is_false( condT );
11133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         else
11134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            mk_skip_over_A32_if_cond_is_false( condT );
11135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         condT = IRTemp_INVALID;
11136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
11137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Ok, now we're unconditional.  Do the load or store. */
11138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* get the old Rn value */
11140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp rnT = newTemp(Ity_I32);
11141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign(rnT, align4if(isT ? getIRegT(rN) : getIRegA(rN),
11142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           rN == 15));
11143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* make a new value for Rn, post-insn */
11145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp rnTnew = IRTemp_INVALID;
11146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (summary == 2 || summary == 3) {
11147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         rnTnew = newTemp(Ity_I32);
11148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign(rnTnew, binop(summary == 2 ? Iop_Add32 : Iop_Sub32,
11149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              mkexpr(rnT),
11150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              mkU32(8 * nRegs)));
11151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
11152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* decide on the base transfer address */
11154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp taT = newTemp(Ity_I32);
11155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign(taT, summary == 3 ? mkexpr(rnTnew) : mkexpr(rnT));
11156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* update Rn if necessary -- in case 3, we're moving it down, so
11158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         update before any memory reference, in order to keep Memcheck
11159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         and V's stack-extending logic (on linux) happy */
11160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (summary == 3) {
11161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (isT)
11162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            putIRegT(rN, mkexpr(rnTnew), IRTemp_INVALID);
11163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         else
11164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            putIRegA(rN, mkexpr(rnTnew), IRTemp_INVALID, Ijk_Boring);
11165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
11166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* generate the transfers */
11168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      for (i = 0; i < nRegs; i++) {
11169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRExpr* addr = binop(Iop_Add32, mkexpr(taT), mkU32(8*i));
11170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (bL) {
11171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            putDReg(dD + i, loadLE(Ity_F64, addr), IRTemp_INVALID);
11172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
11173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            storeLE(addr, getDReg(dD + i));
11174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
11175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
11176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* update Rn if necessary -- in case 2, we're moving it up, so
11178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         update after any memory reference, in order to keep Memcheck
11179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         and V's stack-extending logic (on linux) happy */
11180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (summary == 2) {
11181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (isT)
11182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            putIRegT(rN, mkexpr(rnTnew), IRTemp_INVALID);
11183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         else
11184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            putIRegA(rN, mkexpr(rnTnew), IRTemp_INVALID, Ijk_Boring);
11185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
11186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HChar* nm = bL==1 ? "ld" : "st";
11188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch (summary) {
11189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case 1:  DIP("f%smd%s r%u, {d%u-d%u}\n",
11190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      nm, nCC(conq), rN, dD, dD + nRegs - 1);
11191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  break;
11192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case 2:  DIP("f%smiad%s r%u!, {d%u-d%u}\n",
11193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      nm, nCC(conq), rN, dD, dD + nRegs - 1);
11194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  break;
11195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case 3:  DIP("f%smdbd%s r%u!, {d%u-d%u}\n",
11196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      nm, nCC(conq), rN, dD, dD + nRegs - 1);
11197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  break;
11198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         default: vassert(0);
11199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
11200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      goto decode_success_vfp;
11202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* FIXME alignment constraints? */
11203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
11204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  after_vfp_fldmd_fstmd:
11206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* ------------------- fmrx, fmxr ------------------- */
11208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (BITS8(1,1,1,0,1,1,1,1) == INSN(27,20)
11209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && BITS4(1,0,1,0) == INSN(11,8)
11210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && BITS8(0,0,0,1,0,0,0,0) == (insn28 & 0xFF)) {
11211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt rD  = INSN(15,12);
11212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt reg = INSN(19,16);
11213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (reg == BITS4(0,0,0,1)) {
11214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (rD == 15) {
11215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            IRTemp nzcvT = newTemp(Ity_I32);
11216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* When rD is 15, we are copying the top 4 bits of FPSCR
11217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               into CPSR.  That is, set the flags thunk to COPY and
11218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               install FPSCR[31:28] as the value to copy. */
11219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            assign(nzcvT, binop(Iop_And32,
11220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                IRExpr_Get(OFFB_FPSCR, Ity_I32),
11221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                mkU32(0xF0000000)));
11222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            setFlags_D1(ARMG_CC_OP_COPY, nzcvT, condT);
11223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            DIP("fmstat%s\n", nCC(conq));
11224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
11225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* Otherwise, merely transfer FPSCR to r0 .. r14. */
11226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            IRExpr* e = IRExpr_Get(OFFB_FPSCR, Ity_I32);
11227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (isT)
11228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               putIRegT(rD, e, condT);
11229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            else
11230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               putIRegA(rD, e, condT, Ijk_Boring);
11231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            DIP("fmrx%s r%u, fpscr\n", nCC(conq), rD);
11232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
11233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto decode_success_vfp;
11234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
11235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* fall through */
11236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
11237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (BITS8(1,1,1,0,1,1,1,0) == INSN(27,20)
11239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && BITS4(1,0,1,0) == INSN(11,8)
11240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && BITS8(0,0,0,1,0,0,0,0) == (insn28 & 0xFF)) {
11241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt rD  = INSN(15,12);
11242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt reg = INSN(19,16);
11243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (reg == BITS4(0,0,0,1)) {
11244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putMiscReg32(OFFB_FPSCR,
11245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      isT ? getIRegT(rD) : getIRegA(rD), condT);
11246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("fmxr%s fpscr, r%u\n", nCC(conq), rD);
11247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto decode_success_vfp;
11248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
11249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* fall through */
11250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
11251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* --------------------- vmov --------------------- */
11253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // VMOV dM, rD, rN
11254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (0x0C400B10 == (insn28 & 0x0FF00FD0)) {
11255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt dM = INSN(3,0) | (INSN(5,5) << 4);
11256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt rD = INSN(15,12); /* lo32 */
11257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt rN = INSN(19,16); /* hi32 */
11258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (rD == 15 || rN == 15 || (isT && (rD == 13 || rN == 13))) {
11259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* fall through */
11260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else {
11261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putDReg(dM,
11262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 unop(Iop_ReinterpI64asF64,
11263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      binop(Iop_32HLto64,
11264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            isT ? getIRegT(rN) : getIRegA(rN),
11265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            isT ? getIRegT(rD) : getIRegA(rD))),
11266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 condT);
11267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("vmov%s d%u, r%u, r%u\n", nCC(conq), dM, rD, rN);
11268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto decode_success_vfp;
11269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
11270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* fall through */
11271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
11272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // VMOV rD, rN, dM
11274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (0x0C500B10 == (insn28 & 0x0FF00FD0)) {
11275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt dM = INSN(3,0) | (INSN(5,5) << 4);
11276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt rD = INSN(15,12); /* lo32 */
11277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt rN = INSN(19,16); /* hi32 */
11278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (rD == 15 || rN == 15 || (isT && (rD == 13 || rN == 13))
11279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          || rD == rN) {
11280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* fall through */
11281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else {
11282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp i64 = newTemp(Ity_I64);
11283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign(i64, unop(Iop_ReinterpF64asI64, getDReg(dM)));
11284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRExpr* hi32 = unop(Iop_64HIto32, mkexpr(i64));
11285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRExpr* lo32 = unop(Iop_64to32,   mkexpr(i64));
11286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (isT) {
11287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            putIRegT(rN, hi32, condT);
11288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            putIRegT(rD, lo32, condT);
11289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
11290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            putIRegA(rN, hi32, condT, Ijk_Boring);
11291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            putIRegA(rD, lo32, condT, Ijk_Boring);
11292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
11293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("vmov%s r%u, r%u, d%u\n", nCC(conq), rD, rN, dM);
11294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto decode_success_vfp;
11295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
11296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* fall through */
11297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
11298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // VMOV sD, sD+1, rN, rM
11300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (0x0C400A10 == (insn28 & 0x0FF00FD0)) {
11301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt sD = (INSN(3,0) << 1) | INSN(5,5);
11302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt rN = INSN(15,12);
11303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt rM = INSN(19,16);
11304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (rM == 15 || rN == 15 || (isT && (rM == 13 || rN == 13))
11305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          || sD == 31) {
11306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* fall through */
11307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else {
11308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putFReg(sD,
11309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 unop(Iop_ReinterpI32asF32, isT ? getIRegT(rN) : getIRegA(rN)),
11310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 condT);
11311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putFReg(sD+1,
11312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 unop(Iop_ReinterpI32asF32, isT ? getIRegT(rM) : getIRegA(rM)),
11313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 condT);
11314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("vmov%s, s%u, s%u, r%u, r%u\n",
11315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              nCC(conq), sD, sD + 1, rN, rM);
11316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto decode_success_vfp;
11317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
11318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
11319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // VMOV rN, rM, sD, sD+1
11321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (0x0C500A10 == (insn28 & 0x0FF00FD0)) {
11322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt sD = (INSN(3,0) << 1) | INSN(5,5);
11323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt rN = INSN(15,12);
11324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt rM = INSN(19,16);
11325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (rM == 15 || rN == 15 || (isT && (rM == 13 || rN == 13))
11326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          || sD == 31 || rN == rM) {
11327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* fall through */
11328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else {
11329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRExpr* res0 = unop(Iop_ReinterpF32asI32, getFReg(sD));
11330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRExpr* res1 = unop(Iop_ReinterpF32asI32, getFReg(sD+1));
11331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (isT) {
11332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            putIRegT(rN, res0, condT);
11333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            putIRegT(rM, res1, condT);
11334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
11335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            putIRegA(rN, res0, condT, Ijk_Boring);
11336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            putIRegA(rM, res1, condT, Ijk_Boring);
11337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
11338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("vmov%s, r%u, r%u, s%u, s%u\n",
11339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             nCC(conq), rN, rM, sD, sD + 1);
11340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto decode_success_vfp;
11341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
11342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
11343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // VMOV rD[x], rT  (ARM core register to scalar)
11345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (0x0E000B10 == (insn28 & 0x0F900F1F)) {
11346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt rD  = (INSN(7,7) << 4) | INSN(19,16);
11347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt rT  = INSN(15,12);
11348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt opc = (INSN(22,21) << 2) | INSN(6,5);
11349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt index;
11350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (rT == 15 || (isT && rT == 13)) {
11351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* fall through */
11352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else {
11353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if ((opc & BITS4(1,0,0,0)) == BITS4(1,0,0,0)) {
11354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            index = opc & 7;
11355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            putDRegI64(rD, triop(Iop_SetElem8x8,
11356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                 getDRegI64(rD),
11357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                 mkU8(index),
11358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                 unop(Iop_32to8,
11359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                      isT ? getIRegT(rT) : getIRegA(rT))),
11360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           condT);
11361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            DIP("vmov%s.8 d%u[%u], r%u\n", nCC(conq), rD, index, rT);
11362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto decode_success_vfp;
11363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
11364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         else if ((opc & BITS4(1,0,0,1)) == BITS4(0,0,0,1)) {
11365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            index = (opc >> 1) & 3;
11366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            putDRegI64(rD, triop(Iop_SetElem16x4,
11367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                 getDRegI64(rD),
11368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                 mkU8(index),
11369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                 unop(Iop_32to16,
11370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                      isT ? getIRegT(rT) : getIRegA(rT))),
11371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           condT);
11372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            DIP("vmov%s.16 d%u[%u], r%u\n", nCC(conq), rD, index, rT);
11373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto decode_success_vfp;
11374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
11375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         else if ((opc & BITS4(1,0,1,1)) == BITS4(0,0,0,0)) {
11376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            index = (opc >> 2) & 1;
11377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            putDRegI64(rD, triop(Iop_SetElem32x2,
11378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                 getDRegI64(rD),
11379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                 mkU8(index),
11380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                 isT ? getIRegT(rT) : getIRegA(rT)),
11381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           condT);
11382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            DIP("vmov%s.32 d%u[%u], r%u\n", nCC(conq), rD, index, rT);
11383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto decode_success_vfp;
11384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
11385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* fall through */
11386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
11387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
11388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
11389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // VMOV (scalar to ARM core register)
11391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // VMOV rT, rD[x]
11392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (0x0E100B10 == (insn28 & 0x0F100F1F)) {
11393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt rN  = (INSN(7,7) << 4) | INSN(19,16);
11394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt rT  = INSN(15,12);
11395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt U   = INSN(23,23);
11396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt opc = (INSN(22,21) << 2) | INSN(6,5);
11397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt index;
11398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (rT == 15 || (isT && rT == 13)) {
11399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* fall through */
11400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else {
11401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if ((opc & BITS4(1,0,0,0)) == BITS4(1,0,0,0)) {
11402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            index = opc & 7;
11403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            IRExpr* e = unop(U ? Iop_8Uto32 : Iop_8Sto32,
11404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             binop(Iop_GetElem8x8,
11405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                   getDRegI64(rN),
11406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                   mkU8(index)));
11407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (isT)
11408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               putIRegT(rT, e, condT);
11409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            else
11410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               putIRegA(rT, e, condT, Ijk_Boring);
11411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            DIP("vmov%s.%c8 r%u, d%u[%u]\n", nCC(conq), U ? 'u' : 's',
11412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  rT, rN, index);
11413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto decode_success_vfp;
11414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
11415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         else if ((opc & BITS4(1,0,0,1)) == BITS4(0,0,0,1)) {
11416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            index = (opc >> 1) & 3;
11417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            IRExpr* e = unop(U ? Iop_16Uto32 : Iop_16Sto32,
11418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             binop(Iop_GetElem16x4,
11419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                   getDRegI64(rN),
11420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                   mkU8(index)));
11421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (isT)
11422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               putIRegT(rT, e, condT);
11423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            else
11424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               putIRegA(rT, e, condT, Ijk_Boring);
11425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            DIP("vmov%s.%c16 r%u, d%u[%u]\n", nCC(conq), U ? 'u' : 's',
11426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  rT, rN, index);
11427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto decode_success_vfp;
11428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
11429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         else if ((opc & BITS4(1,0,1,1)) == BITS4(0,0,0,0) && U == 0) {
11430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            index = (opc >> 2) & 1;
11431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            IRExpr* e = binop(Iop_GetElem32x2, getDRegI64(rN), mkU8(index));
11432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (isT)
11433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               putIRegT(rT, e, condT);
11434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            else
11435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               putIRegA(rT, e, condT, Ijk_Boring);
11436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            DIP("vmov%s.32 r%u, d%u[%u]\n", nCC(conq), rT, rN, index);
11437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto decode_success_vfp;
11438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
11439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* fall through */
11440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
11441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
11442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
11443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // VMOV.F32 sD, #imm
11445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // FCONSTS sD, #imm
11446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (BITS8(1,1,1,0,1,0,1,1) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,1))
11447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && BITS4(0,0,0,0) == INSN(7,4) && INSN(11,8) == BITS4(1,0,1,0)) {
11448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt rD   = (INSN(15,12) << 1) | INSN(22,22);
11449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt imm8 = (INSN(19,16) << 4) | INSN(3,0);
11450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt b    = (imm8 >> 6) & 1;
11451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt imm;
11452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      imm = (BITS8((imm8 >> 7) & 1,(~b) & 1,b,b,b,b,b,(imm8 >> 5) & 1) << 8)
11453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             | ((imm8 & 0x1f) << 3);
11454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      imm <<= 16;
11455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putFReg(rD, unop(Iop_ReinterpI32asF32, mkU32(imm)), condT);
11456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("fconsts%s s%u #%u", nCC(conq), rD, imm8);
11457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      goto decode_success_vfp;
11458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
11459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // VMOV.F64 dD, #imm
11461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // FCONSTD dD, #imm
11462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (BITS8(1,1,1,0,1,0,1,1) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,1))
11463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && BITS4(0,0,0,0) == INSN(7,4) && INSN(11,8) == BITS4(1,0,1,1)) {
11464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt rD   = INSN(15,12) | (INSN(22,22) << 4);
11465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt imm8 = (INSN(19,16) << 4) | INSN(3,0);
11466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt b    = (imm8 >> 6) & 1;
11467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ULong imm;
11468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      imm = (BITS8((imm8 >> 7) & 1,(~b) & 1,b,b,b,b,b,b) << 8)
11469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             | BITS8(b,b,0,0,0,0,0,0) | (imm8 & 0x3f);
11470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      imm <<= 48;
11471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putDReg(rD, unop(Iop_ReinterpI64asF64, mkU64(imm)), condT);
11472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("fconstd%s d%u #%u", nCC(conq), rD, imm8);
11473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      goto decode_success_vfp;
11474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
11475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* ---------------------- vdup ------------------------- */
11477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // VDUP dD, rT
11478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // VDUP qD, rT
11479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (BITS8(1,1,1,0,1,0,0,0) == (INSN(27,20) & BITS8(1,1,1,1,1,0,0,1))
11480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && BITS4(1,0,1,1) == INSN(11,8) && INSN(6,6) == 0 && INSN(4,4) == 1) {
11481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt rD   = (INSN(7,7) << 4) | INSN(19,16);
11482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt rT   = INSN(15,12);
11483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt Q    = INSN(21,21);
11484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt size = (INSN(22,22) << 1) | INSN(5,5);
11485f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root      if (rT == 15 || (isT && rT == 13) || size == 3 || (Q && (rD & 1))) {
11486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* fall through */
11487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else {
11488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRExpr* e = isT ? getIRegT(rT) : getIRegA(rT);
11489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (Q) {
11490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            rD >>= 1;
11491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            switch (size) {
11492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               case 0:
11493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  putQReg(rD, unop(Iop_Dup32x4, e), condT);
11494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  break;
11495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               case 1:
11496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  putQReg(rD, unop(Iop_Dup16x8, unop(Iop_32to16, e)),
11497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              condT);
11498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  break;
11499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               case 2:
11500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  putQReg(rD, unop(Iop_Dup8x16, unop(Iop_32to8, e)),
11501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              condT);
11502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  break;
11503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               default:
11504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  vassert(0);
11505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
11506ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            DIP("vdup.%u q%u, r%u\n", 32 / (1<<size), rD, rT);
11507ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
11508ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            switch (size) {
11509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               case 0:
11510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  putDRegI64(rD, unop(Iop_Dup32x2, e), condT);
11511ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  break;
11512ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               case 1:
11513ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  putDRegI64(rD, unop(Iop_Dup16x4, unop(Iop_32to16, e)),
11514ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               condT);
11515ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  break;
11516ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               case 2:
11517ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  putDRegI64(rD, unop(Iop_Dup8x8, unop(Iop_32to8, e)),
11518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               condT);
11519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  break;
11520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               default:
11521ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  vassert(0);
11522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
11523ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            DIP("vdup.%u d%u, r%u\n", 32 / (1<<size), rD, rT);
11524ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
11525ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto decode_success_vfp;
11526ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
11527ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
11528ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11529ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* --------------------- f{ld,st}d --------------------- */
11530ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // FLDD, FSTD
11531ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (BITS8(1,1,0,1,0,0,0,0) == (INSN(27,20) & BITS8(1,1,1,1,0,0,1,0))
11532ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && BITS4(1,0,1,1) == INSN(11,8)) {
11533ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt dD     = INSN(15,12) | (INSN(22,22) << 4);
11534ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt rN     = INSN(19,16);
11535ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt offset = (insn28 & 0xFF) << 2;
11536ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt bU     = (insn28 >> 23) & 1; /* 1: +offset  0: -offset */
11537ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt bL     = (insn28 >> 20) & 1; /* 1: load  0: store */
11538ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* make unconditional */
11539ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (condT != IRTemp_INVALID) {
11540ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (isT)
11541ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            mk_skip_over_T32_if_cond_is_false( condT );
11542ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         else
11543ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            mk_skip_over_A32_if_cond_is_false( condT );
11544ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         condT = IRTemp_INVALID;
11545ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
11546ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp ea = newTemp(Ity_I32);
11547ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign(ea, binop(bU ? Iop_Add32 : Iop_Sub32,
11548ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       align4if(isT ? getIRegT(rN) : getIRegA(rN),
11549ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                rN == 15),
11550ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       mkU32(offset)));
11551ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (bL) {
11552ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putDReg(dD, loadLE(Ity_F64,mkexpr(ea)), IRTemp_INVALID);
11553ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else {
11554ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         storeLE(mkexpr(ea), getDReg(dD));
11555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
11556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("f%sd%s d%u, [r%u, %c#%u]\n",
11557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          bL ? "ld" : "st", nCC(conq), dD, rN,
11558ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          bU ? '+' : '-', offset);
11559ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      goto decode_success_vfp;
11560ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
11561ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* --------------------- dp insns (D) --------------------- */
11563ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (BITS8(1,1,1,0,0,0,0,0) == (INSN(27,20) & BITS8(1,1,1,1,0,0,0,0))
11564ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && BITS4(1,0,1,1) == INSN(11,8)
11565ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && BITS4(0,0,0,0) == (INSN(7,4) & BITS4(0,0,0,1))) {
11566ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt    dM  = INSN(3,0)   | (INSN(5,5) << 4);       /* argR */
11567ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt    dD  = INSN(15,12) | (INSN(22,22) << 4);   /* dst/acc */
11568ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt    dN  = INSN(19,16) | (INSN(7,7) << 4);     /* argL */
11569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt    bP  = (insn28 >> 23) & 1;
11570ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt    bQ  = (insn28 >> 21) & 1;
11571ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt    bR  = (insn28 >> 20) & 1;
11572ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt    bS  = (insn28 >> 6) & 1;
11573ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt    opc = (bP << 3) | (bQ << 2) | (bR << 1) | bS;
11574ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRExpr* rm  = get_FAKE_roundingmode(); /* XXXROUNDINGFIXME */
11575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch (opc) {
11576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case BITS4(0,0,0,0): /* MAC: d + n * m */
11577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            putDReg(dD, triop(Iop_AddF64, rm,
11578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              getDReg(dD),
11579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              triop(Iop_MulF64, rm, getDReg(dN),
11580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                                    getDReg(dM))),
11581ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        condT);
11582ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            DIP("fmacd%s d%u, d%u, d%u\n", nCC(conq), dD, dN, dM);
11583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto decode_success_vfp;
11584ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case BITS4(0,0,0,1): /* NMAC: d + -(n * m) */
11585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            putDReg(dD, triop(Iop_AddF64, rm,
11586ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              getDReg(dD),
11587ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              unop(Iop_NegF64,
11588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                   triop(Iop_MulF64, rm, getDReg(dN),
11589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                                         getDReg(dM)))),
11590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        condT);
11591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            DIP("fnmacd%s d%u, d%u, d%u\n", nCC(conq), dD, dN, dM);
11592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto decode_success_vfp;
11593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case BITS4(0,0,1,0): /* MSC: - d + n * m */
11594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            putDReg(dD, triop(Iop_AddF64, rm,
11595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              unop(Iop_NegF64, getDReg(dD)),
11596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              triop(Iop_MulF64, rm, getDReg(dN),
11597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                                    getDReg(dM))),
11598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        condT);
11599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            DIP("fmscd%s d%u, d%u, d%u\n", nCC(conq), dD, dN, dM);
11600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto decode_success_vfp;
11601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case BITS4(0,0,1,1): /* NMSC: - d + -(n * m) */
11602ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            putDReg(dD, triop(Iop_AddF64, rm,
11603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              unop(Iop_NegF64, getDReg(dD)),
11604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              unop(Iop_NegF64,
11605ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                   triop(Iop_MulF64, rm, getDReg(dN),
11606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                                         getDReg(dM)))),
11607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        condT);
11608ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            DIP("fnmscd%s d%u, d%u, d%u\n", nCC(conq), dD, dN, dM);
11609ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto decode_success_vfp;
11610ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case BITS4(0,1,0,0): /* MUL: n * m */
11611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            putDReg(dD, triop(Iop_MulF64, rm, getDReg(dN), getDReg(dM)),
11612ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        condT);
11613ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            DIP("fmuld%s d%u, d%u, d%u\n", nCC(conq), dD, dN, dM);
11614ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto decode_success_vfp;
11615ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case BITS4(0,1,0,1): /* NMUL: - n * m */
11616ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            putDReg(dD, unop(Iop_NegF64,
11617ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             triop(Iop_MulF64, rm, getDReg(dN),
11618ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                                   getDReg(dM))),
11619ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    condT);
11620ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            DIP("fnmuld%s d%u, d%u, d%u\n", nCC(conq), dD, dN, dM);
11621ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto decode_success_vfp;
11622ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case BITS4(0,1,1,0): /* ADD: n + m */
11623ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            putDReg(dD, triop(Iop_AddF64, rm, getDReg(dN), getDReg(dM)),
11624ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        condT);
11625ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            DIP("faddd%s d%u, d%u, d%u\n", nCC(conq), dD, dN, dM);
11626ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto decode_success_vfp;
11627ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case BITS4(0,1,1,1): /* SUB: n - m */
11628ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            putDReg(dD, triop(Iop_SubF64, rm, getDReg(dN), getDReg(dM)),
11629ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        condT);
11630ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            DIP("fsubd%s d%u, d%u, d%u\n", nCC(conq), dD, dN, dM);
11631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto decode_success_vfp;
11632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case BITS4(1,0,0,0): /* DIV: n / m */
11633ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            putDReg(dD, triop(Iop_DivF64, rm, getDReg(dN), getDReg(dM)),
11634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        condT);
11635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            DIP("fdivd%s d%u, d%u, d%u\n", nCC(conq), dD, dN, dM);
11636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto decode_success_vfp;
11637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         default:
11638ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
11639ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
11640ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
11641ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11642ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* --------------------- compares (D) --------------------- */
11643ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /*          31   27   23   19   15 11   7    3
11644ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 28   24   20   16 12    8    4    0
11645ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      FCMPD    cond 1110 1D11 0100 Dd 1011 0100 Dm
11646ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      FCMPED   cond 1110 1D11 0100 Dd 1011 1100 Dm
11647ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      FCMPZD   cond 1110 1D11 0101 Dd 1011 0100 0000
11648ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      FCMPZED  cond 1110 1D11 0101 Dd 1011 1100 0000
11649ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                 Z         N
11650ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Z=0 Compare Dd vs Dm     and set FPSCR 31:28 accordingly
11652ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Z=1 Compare Dd vs zero
11653ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11654ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      N=1 generates Invalid Operation exn if either arg is any kind of NaN
11655ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      N=0 generates Invalid Operation exn if either arg is a signalling NaN
11656ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      (Not that we pay any attention to N here)
11657ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   */
11658ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (BITS8(1,1,1,0,1,0,1,1) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,1))
11659ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && BITS4(0,1,0,0) == (INSN(19,16) & BITS4(1,1,1,0))
11660ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && BITS4(1,0,1,1) == INSN(11,8)
11661ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && BITS4(0,1,0,0) == (INSN(7,4) & BITS4(0,1,0,1))) {
11662ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt bZ = (insn28 >> 16) & 1;
11663ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt bN = (insn28 >> 7) & 1;
11664ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt dD = INSN(15,12) | (INSN(22,22) << 4);
11665ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt dM = INSN(3,0) | (INSN(5,5) << 4);
11666ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (bZ && INSN(3,0) != 0) {
11667ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* does not decode; fall through */
11668ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else {
11669ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp argL = newTemp(Ity_F64);
11670ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp argR = newTemp(Ity_F64);
11671ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp irRes = newTemp(Ity_I32);
11672ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign(argL, getDReg(dD));
11673ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign(argR, bZ ? IRExpr_Const(IRConst_F64i(0)) : getDReg(dM));
11674ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign(irRes, binop(Iop_CmpF64, mkexpr(argL), mkexpr(argR)));
11675ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11676ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp nzcv     = IRTemp_INVALID;
11677ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp oldFPSCR = newTemp(Ity_I32);
11678ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp newFPSCR = newTemp(Ity_I32);
11679ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11680ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* This is where the fun starts.  We have to convert 'irRes'
11681ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            from an IR-convention return result (IRCmpF64Result) to an
11682ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ARM-encoded (N,Z,C,V) group.  The final result is in the
11683ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            bottom 4 bits of 'nzcv'. */
11684ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Map compare result from IR to ARM(nzcv) */
11685ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /*
11686ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            FP cmp result | IR   | ARM(nzcv)
11687ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            --------------------------------
11688ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            UN              0x45   0011
11689ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            LT              0x01   1000
11690ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            GT              0x00   0010
11691ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            EQ              0x40   0110
11692ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         */
11693ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         nzcv = mk_convert_IRCmpF64Result_to_NZCV(irRes);
11694ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11695ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* And update FPSCR accordingly */
11696ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign(oldFPSCR, IRExpr_Get(OFFB_FPSCR, Ity_I32));
11697ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign(newFPSCR,
11698ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                binop(Iop_Or32,
11699ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      binop(Iop_And32, mkexpr(oldFPSCR), mkU32(0x0FFFFFFF)),
11700ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      binop(Iop_Shl32, mkexpr(nzcv), mkU8(28))));
11701ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11702ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putMiscReg32(OFFB_FPSCR, mkexpr(newFPSCR), condT);
11703ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11704ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (bZ) {
11705ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            DIP("fcmpz%sd%s d%u\n", bN ? "e" : "", nCC(conq), dD);
11706ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
11707ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            DIP("fcmp%sd%s d%u, d%u\n", bN ? "e" : "", nCC(conq), dD, dM);
11708ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
11709ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto decode_success_vfp;
11710ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
11711ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* fall through */
11712ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
11713ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11714ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* --------------------- unary (D) --------------------- */
11715ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (BITS8(1,1,1,0,1,0,1,1) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,1))
11716ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && BITS4(0,0,0,0) == (INSN(19,16) & BITS4(1,1,1,0))
11717ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && BITS4(1,0,1,1) == INSN(11,8)
11718ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && BITS4(0,1,0,0) == (INSN(7,4) & BITS4(0,1,0,1))) {
11719ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt dD  = INSN(15,12) | (INSN(22,22) << 4);
11720ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt dM  = INSN(3,0) | (INSN(5,5) << 4);
11721ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt b16 = (insn28 >> 16) & 1;
11722ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt b7  = (insn28 >> 7) & 1;
11723ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /**/ if (b16 == 0 && b7 == 0) {
11724ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         // FCPYD
11725ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putDReg(dD, getDReg(dM), condT);
11726ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("fcpyd%s d%u, d%u\n", nCC(conq), dD, dM);
11727ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto decode_success_vfp;
11728ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
11729ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      else if (b16 == 0 && b7 == 1) {
11730ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         // FABSD
11731ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putDReg(dD, unop(Iop_AbsF64, getDReg(dM)), condT);
11732ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("fabsd%s d%u, d%u\n", nCC(conq), dD, dM);
11733ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto decode_success_vfp;
11734ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
11735ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      else if (b16 == 1 && b7 == 0) {
11736ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         // FNEGD
11737ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putDReg(dD, unop(Iop_NegF64, getDReg(dM)), condT);
11738ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("fnegd%s d%u, d%u\n", nCC(conq), dD, dM);
11739ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto decode_success_vfp;
11740ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
11741ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      else if (b16 == 1 && b7 == 1) {
11742ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         // FSQRTD
11743ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRExpr* rm = get_FAKE_roundingmode(); /* XXXROUNDINGFIXME */
11744ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putDReg(dD, binop(Iop_SqrtF64, rm, getDReg(dM)), condT);
11745ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("fsqrtd%s d%u, d%u\n", nCC(conq), dD, dM);
11746ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto decode_success_vfp;
11747ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
11748ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      else
11749ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(0);
11750ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11751ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* fall through */
11752ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
11753ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11754ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* ----------------- I <-> D conversions ----------------- */
11755ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11756ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // F{S,U}ITOD dD, fM
11757ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (BITS8(1,1,1,0,1,0,1,1) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,1))
11758ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && BITS4(1,0,0,0) == (INSN(19,16) & BITS4(1,1,1,1))
11759ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && BITS4(1,0,1,1) == INSN(11,8)
11760ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && BITS4(0,1,0,0) == (INSN(7,4) & BITS4(0,1,0,1))) {
11761ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt bM    = (insn28 >> 5) & 1;
11762ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt fM    = (INSN(3,0) << 1) | bM;
11763ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt dD    = INSN(15,12) | (INSN(22,22) << 4);
11764ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt syned = (insn28 >> 7) & 1;
11765ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (syned) {
11766ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         // FSITOD
11767ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putDReg(dD, unop(Iop_I32StoF64,
11768ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          unop(Iop_ReinterpF32asI32, getFReg(fM))),
11769ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 condT);
11770ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("fsitod%s d%u, s%u\n", nCC(conq), dD, fM);
11771ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else {
11772ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         // FUITOD
11773ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putDReg(dD, unop(Iop_I32UtoF64,
11774ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          unop(Iop_ReinterpF32asI32, getFReg(fM))),
11775ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 condT);
11776ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("fuitod%s d%u, s%u\n", nCC(conq), dD, fM);
11777ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
11778ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      goto decode_success_vfp;
11779ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
11780ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11781ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // FTO{S,U}ID fD, dM
11782ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (BITS8(1,1,1,0,1,0,1,1) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,1))
11783ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && BITS4(1,1,0,0) == (INSN(19,16) & BITS4(1,1,1,0))
11784ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && BITS4(1,0,1,1) == INSN(11,8)
11785ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && BITS4(0,1,0,0) == (INSN(7,4) & BITS4(0,1,0,1))) {
11786ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt   bD    = (insn28 >> 22) & 1;
11787ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt   fD    = (INSN(15,12) << 1) | bD;
11788ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt   dM    = INSN(3,0) | (INSN(5,5) << 4);
11789ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt   bZ    = (insn28 >> 7) & 1;
11790ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt   syned = (insn28 >> 16) & 1;
11791ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp rmode = newTemp(Ity_I32);
11792ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign(rmode, bZ ? mkU32(Irrm_ZERO)
11793ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       : mkexpr(mk_get_IR_rounding_mode()));
11794ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (syned) {
11795ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         // FTOSID
11796ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putFReg(fD, unop(Iop_ReinterpI32asF32,
11797ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          binop(Iop_F64toI32S, mkexpr(rmode),
11798ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                getDReg(dM))),
11799ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 condT);
11800ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("ftosi%sd%s s%u, d%u\n", bZ ? "z" : "",
11801ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             nCC(conq), fD, dM);
11802ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else {
11803ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         // FTOUID
11804ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putFReg(fD, unop(Iop_ReinterpI32asF32,
11805ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          binop(Iop_F64toI32U, mkexpr(rmode),
11806ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                getDReg(dM))),
11807ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 condT);
11808ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("ftoui%sd%s s%u, d%u\n", bZ ? "z" : "",
11809ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             nCC(conq), fD, dM);
11810ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
11811ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      goto decode_success_vfp;
11812ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
11813ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11814ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* ----------------------------------------------------------- */
11815ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* -- VFP instructions -- single precision                  -- */
11816ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* ----------------------------------------------------------- */
11817ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11818ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* --------------------- fldms, fstms --------------------- */
11819ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /*
11820ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                 31   27   23   19 15 11   7   0
11821ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                         P UDWL
11822ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      C4-98, C5-26   1  FSTMD    cond 1100 1x00 Rn Fd 1010 offset
11823ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      C4-98, C5-28   2  FSTMDIA  cond 1100 1x10 Rn Fd 1010 offset
11824ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      C4-98, C5-30   3  FSTMDDB  cond 1101 0x10 Rn Fd 1010 offset
11825ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11826ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      C4-40, C5-26   1  FLDMD    cond 1100 1x01 Rn Fd 1010 offset
11827ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      C4-40, C5-26   2  FLDMIAD  cond 1100 1x11 Rn Fd 1010 offset
11828ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      C4-40, C5-26   3  FLDMDBD  cond 1101 0x11 Rn Fd 1010 offset
11829ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11830ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Regs transferred: F(Fd:D) .. F(Fd:d + offset)
11831ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      offset must not imply a reg > 15
11832ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IA/DB: Rn is changed by (4 x # regs transferred)
11833ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11834ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case coding:
11835ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         1  at-Rn   (access at Rn)
11836ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         2  ia-Rn   (access at Rn, then Rn += 4n)
11837ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         3  db-Rn   (Rn -= 4n,     then access at Rn)
11838ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   */
11839ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (BITS8(1,1,0,0,0,0,0,0) == (INSN(27,20) & BITS8(1,1,1,0,0,0,0,0))
11840ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && INSN(11,8) == BITS4(1,0,1,0)) {
11841ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt bP      = (insn28 >> 24) & 1;
11842ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt bU      = (insn28 >> 23) & 1;
11843ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt bW      = (insn28 >> 21) & 1;
11844ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt bL      = (insn28 >> 20) & 1;
11845ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt bD      = (insn28 >> 22) & 1;
11846ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt offset  = (insn28 >> 0) & 0xFF;
11847ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt rN      = INSN(19,16);
11848ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt fD      = (INSN(15,12) << 1) | bD;
11849ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt nRegs   = offset;
11850ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt summary = 0;
11851ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Int  i;
11852ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11853ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /**/ if (bP == 0 && bU == 1 && bW == 0) {
11854ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         summary = 1;
11855ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
11856ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      else if (bP == 0 && bU == 1 && bW == 1) {
11857ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         summary = 2;
11858ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
11859ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      else if (bP == 1 && bU == 0 && bW == 1) {
11860ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         summary = 3;
11861ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
11862ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      else goto after_vfp_fldms_fstms;
11863ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11864ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* no writebacks to r15 allowed.  No use of r15 in thumb mode. */
11865ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (rN == 15 && (summary == 2 || summary == 3 || isT))
11866ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto after_vfp_fldms_fstms;
11867ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11868ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* offset must specify at least one register */
11869ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (offset < 1)
11870ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto after_vfp_fldms_fstms;
11871ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11872ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* can't transfer regs after S31 */
11873ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (fD + nRegs - 1 >= 32)
11874ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto after_vfp_fldms_fstms;
11875ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11876ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Now, we can't do a conditional load or store, since that very
11877ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         likely will generate an exception.  So we have to take a side
11878ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         exit at this point if the condition is false. */
11879ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (condT != IRTemp_INVALID) {
11880ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (isT)
11881ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            mk_skip_over_T32_if_cond_is_false( condT );
11882ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         else
11883ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            mk_skip_over_A32_if_cond_is_false( condT );
11884ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         condT = IRTemp_INVALID;
11885ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
11886ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Ok, now we're unconditional.  Do the load or store. */
11887ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11888ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* get the old Rn value */
11889ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp rnT = newTemp(Ity_I32);
11890ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign(rnT, align4if(isT ? getIRegT(rN) : getIRegA(rN),
11891ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           rN == 15));
11892ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11893ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* make a new value for Rn, post-insn */
11894ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp rnTnew = IRTemp_INVALID;
11895ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (summary == 2 || summary == 3) {
11896ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         rnTnew = newTemp(Ity_I32);
11897ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign(rnTnew, binop(summary == 2 ? Iop_Add32 : Iop_Sub32,
11898ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              mkexpr(rnT),
11899ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              mkU32(4 * nRegs)));
11900ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
11901ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11902ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* decide on the base transfer address */
11903ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp taT = newTemp(Ity_I32);
11904ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign(taT, summary == 3 ? mkexpr(rnTnew) : mkexpr(rnT));
11905ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11906ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* update Rn if necessary -- in case 3, we're moving it down, so
11907ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         update before any memory reference, in order to keep Memcheck
11908ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         and V's stack-extending logic (on linux) happy */
11909ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (summary == 3) {
11910ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (isT)
11911ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            putIRegT(rN, mkexpr(rnTnew), IRTemp_INVALID);
11912ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         else
11913ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            putIRegA(rN, mkexpr(rnTnew), IRTemp_INVALID, Ijk_Boring);
11914ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
11915ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11916ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* generate the transfers */
11917ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      for (i = 0; i < nRegs; i++) {
11918ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRExpr* addr = binop(Iop_Add32, mkexpr(taT), mkU32(4*i));
11919ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (bL) {
11920ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            putFReg(fD + i, loadLE(Ity_F32, addr), IRTemp_INVALID);
11921ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
11922ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            storeLE(addr, getFReg(fD + i));
11923ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
11924ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
11925ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11926ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* update Rn if necessary -- in case 2, we're moving it up, so
11927ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         update after any memory reference, in order to keep Memcheck
11928ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         and V's stack-extending logic (on linux) happy */
11929ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (summary == 2) {
11930ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (isT)
11931ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            putIRegT(rN, mkexpr(rnTnew), IRTemp_INVALID);
11932ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         else
11933ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            putIRegA(rN, mkexpr(rnTnew), IRTemp_INVALID, Ijk_Boring);
11934ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
11935ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11936ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HChar* nm = bL==1 ? "ld" : "st";
11937ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch (summary) {
11938ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case 1:  DIP("f%sms%s r%u, {s%u-s%u}\n",
11939ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      nm, nCC(conq), rN, fD, fD + nRegs - 1);
11940ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  break;
11941ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case 2:  DIP("f%smias%s r%u!, {s%u-s%u}\n",
11942ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      nm, nCC(conq), rN, fD, fD + nRegs - 1);
11943ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  break;
11944ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case 3:  DIP("f%smdbs%s r%u!, {s%u-s%u}\n",
11945ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      nm, nCC(conq), rN, fD, fD + nRegs - 1);
11946ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  break;
11947ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         default: vassert(0);
11948ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
11949ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11950ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      goto decode_success_vfp;
11951ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* FIXME alignment constraints? */
11952ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
11953ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11954ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  after_vfp_fldms_fstms:
11955ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11956ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* --------------------- fmsr, fmrs --------------------- */
11957ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (BITS8(1,1,1,0,0,0,0,0) == (INSN(27,20) & BITS8(1,1,1,1,1,1,1,0))
11958ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && BITS4(1,0,1,0) == INSN(11,8)
11959ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && BITS4(0,0,0,0) == INSN(3,0)
11960ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && BITS4(0,0,0,1) == (INSN(7,4) & BITS4(0,1,1,1))) {
11961ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt rD  = INSN(15,12);
11962ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt b7  = (insn28 >> 7) & 1;
11963ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt fN  = (INSN(19,16) << 1) | b7;
11964ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt b20 = (insn28 >> 20) & 1;
11965ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (rD == 15) {
11966ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* fall through */
11967ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Let's assume that no sane person would want to do
11968ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            floating-point transfers to or from the program counter,
11969ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            and simply decline to decode the instruction.  The ARM ARM
11970ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            doesn't seem to explicitly disallow this case, though. */
11971ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else {
11972ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (b20) {
11973ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            IRExpr* res = unop(Iop_ReinterpF32asI32, getFReg(fN));
11974ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (isT)
11975ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               putIRegT(rD, res, condT);
11976ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            else
11977ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               putIRegA(rD, res, condT, Ijk_Boring);
11978ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            DIP("fmrs%s r%u, s%u\n", nCC(conq), rD, fN);
11979ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
11980ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            putFReg(fN, unop(Iop_ReinterpI32asF32,
11981ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             isT ? getIRegT(rD) : getIRegA(rD)),
11982ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        condT);
11983ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            DIP("fmsr%s s%u, r%u\n", nCC(conq), fN, rD);
11984ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
11985ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto decode_success_vfp;
11986ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
11987ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* fall through */
11988ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
11989ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11990ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* --------------------- f{ld,st}s --------------------- */
11991ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // FLDS, FSTS
11992ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (BITS8(1,1,0,1,0,0,0,0) == (INSN(27,20) & BITS8(1,1,1,1,0,0,1,0))
11993ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && BITS4(1,0,1,0) == INSN(11,8)) {
11994ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt bD     = (insn28 >> 22) & 1;
11995ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt fD     = (INSN(15,12) << 1) | bD;
11996ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt rN     = INSN(19,16);
11997ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt offset = (insn28 & 0xFF) << 2;
11998ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt bU     = (insn28 >> 23) & 1; /* 1: +offset  0: -offset */
11999ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt bL     = (insn28 >> 20) & 1; /* 1: load  0: store */
12000ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* make unconditional */
12001ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (condT != IRTemp_INVALID) {
12002ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (isT)
12003ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            mk_skip_over_T32_if_cond_is_false( condT );
12004ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         else
12005ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            mk_skip_over_A32_if_cond_is_false( condT );
12006ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         condT = IRTemp_INVALID;
12007ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
12008ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp ea = newTemp(Ity_I32);
12009ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign(ea, binop(bU ? Iop_Add32 : Iop_Sub32,
12010ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       align4if(isT ? getIRegT(rN) : getIRegA(rN),
12011ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                rN == 15),
12012ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       mkU32(offset)));
12013ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (bL) {
12014ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putFReg(fD, loadLE(Ity_F32,mkexpr(ea)), IRTemp_INVALID);
12015ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else {
12016ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         storeLE(mkexpr(ea), getFReg(fD));
12017ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
12018ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("f%ss%s s%u, [r%u, %c#%u]\n",
12019ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          bL ? "ld" : "st", nCC(conq), fD, rN,
12020ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          bU ? '+' : '-', offset);
12021ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      goto decode_success_vfp;
12022ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
12023ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12024ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* --------------------- dp insns (F) --------------------- */
12025ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (BITS8(1,1,1,0,0,0,0,0) == (INSN(27,20) & BITS8(1,1,1,1,0,0,0,0))
12026ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && BITS4(1,0,1,0) == (INSN(11,8) & BITS4(1,1,1,0))
12027ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && BITS4(0,0,0,0) == (INSN(7,4) & BITS4(0,0,0,1))) {
12028ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt    bM  = (insn28 >> 5) & 1;
12029ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt    bD  = (insn28 >> 22) & 1;
12030ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt    bN  = (insn28 >> 7) & 1;
12031ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt    fM  = (INSN(3,0) << 1) | bM;   /* argR */
12032ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt    fD  = (INSN(15,12) << 1) | bD; /* dst/acc */
12033ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt    fN  = (INSN(19,16) << 1) | bN; /* argL */
12034ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt    bP  = (insn28 >> 23) & 1;
12035ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt    bQ  = (insn28 >> 21) & 1;
12036ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt    bR  = (insn28 >> 20) & 1;
12037ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt    bS  = (insn28 >> 6) & 1;
12038ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt    opc = (bP << 3) | (bQ << 2) | (bR << 1) | bS;
12039ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRExpr* rm  = get_FAKE_roundingmode(); /* XXXROUNDINGFIXME */
12040ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch (opc) {
12041ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case BITS4(0,0,0,0): /* MAC: d + n * m */
12042ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            putFReg(fD, triop(Iop_AddF32, rm,
12043ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              getFReg(fD),
12044ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              triop(Iop_MulF32, rm, getFReg(fN), getFReg(fM))),
12045ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        condT);
12046ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            DIP("fmacs%s s%u, s%u, s%u\n", nCC(conq), fD, fN, fM);
12047ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto decode_success_vfp;
12048ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case BITS4(0,0,0,1): /* NMAC: d + -(n * m) */
12049ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            putFReg(fD, triop(Iop_AddF32, rm,
12050ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              getFReg(fD),
12051ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              unop(Iop_NegF32,
12052ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                   triop(Iop_MulF32, rm, getFReg(fN),
12053ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                                         getFReg(fM)))),
12054ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        condT);
12055ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            DIP("fnmacs%s s%u, s%u, s%u\n", nCC(conq), fD, fN, fM);
12056ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto decode_success_vfp;
12057ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case BITS4(0,0,1,0): /* MSC: - d + n * m */
12058ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            putFReg(fD, triop(Iop_AddF32, rm,
12059ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              unop(Iop_NegF32, getFReg(fD)),
12060ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              triop(Iop_MulF32, rm, getFReg(fN), getFReg(fM))),
12061ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        condT);
12062ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            DIP("fmscs%s s%u, s%u, s%u\n", nCC(conq), fD, fN, fM);
12063ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto decode_success_vfp;
12064ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case BITS4(0,0,1,1): /* NMSC: - d + -(n * m) */
12065ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            putFReg(fD, triop(Iop_AddF32, rm,
12066ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              unop(Iop_NegF32, getFReg(fD)),
12067ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              unop(Iop_NegF32,
12068ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                   triop(Iop_MulF32, rm,
12069ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                                     getFReg(fN),
12070ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                                    getFReg(fM)))),
12071ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        condT);
12072ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            DIP("fnmscs%s s%u, s%u, s%u\n", nCC(conq), fD, fN, fM);
12073ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto decode_success_vfp;
12074ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case BITS4(0,1,0,0): /* MUL: n * m */
12075ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            putFReg(fD, triop(Iop_MulF32, rm, getFReg(fN), getFReg(fM)),
12076ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        condT);
12077ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            DIP("fmuls%s s%u, s%u, s%u\n", nCC(conq), fD, fN, fM);
12078ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto decode_success_vfp;
12079ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case BITS4(0,1,0,1): /* NMUL: - n * m */
12080ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            putFReg(fD, unop(Iop_NegF32,
12081ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             triop(Iop_MulF32, rm, getFReg(fN),
12082ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                                   getFReg(fM))),
12083ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    condT);
12084ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            DIP("fnmuls%s s%u, s%u, s%u\n", nCC(conq), fD, fN, fM);
12085ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto decode_success_vfp;
12086ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case BITS4(0,1,1,0): /* ADD: n + m */
12087ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            putFReg(fD, triop(Iop_AddF32, rm, getFReg(fN), getFReg(fM)),
12088ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        condT);
12089ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            DIP("fadds%s s%u, s%u, s%u\n", nCC(conq), fD, fN, fM);
12090ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto decode_success_vfp;
12091ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case BITS4(0,1,1,1): /* SUB: n - m */
12092ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            putFReg(fD, triop(Iop_SubF32, rm, getFReg(fN), getFReg(fM)),
12093ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        condT);
12094ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            DIP("fsubs%s s%u, s%u, s%u\n", nCC(conq), fD, fN, fM);
12095ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto decode_success_vfp;
12096ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case BITS4(1,0,0,0): /* DIV: n / m */
12097ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            putFReg(fD, triop(Iop_DivF32, rm, getFReg(fN), getFReg(fM)),
12098ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        condT);
12099ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            DIP("fdivs%s s%u, s%u, s%u\n", nCC(conq), fD, fN, fM);
12100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto decode_success_vfp;
12101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         default:
12102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
12103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
12104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
12105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* --------------------- compares (S) --------------------- */
12107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /*          31   27   23   19   15 11   7    3
12108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 28   24   20   16 12    8    4    0
12109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      FCMPS    cond 1110 1D11 0100 Fd 1010 01M0 Fm
12110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      FCMPES   cond 1110 1D11 0100 Fd 1010 11M0 Fm
12111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      FCMPZS   cond 1110 1D11 0101 Fd 1010 0100 0000
12112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      FCMPZED  cond 1110 1D11 0101 Fd 1010 1100 0000
12113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                 Z         N
12114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Z=0 Compare Fd:D vs Fm:M     and set FPSCR 31:28 accordingly
12116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Z=1 Compare Fd:D vs zero
12117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      N=1 generates Invalid Operation exn if either arg is any kind of NaN
12119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      N=0 generates Invalid Operation exn if either arg is a signalling NaN
12120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      (Not that we pay any attention to N here)
12121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   */
12122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (BITS8(1,1,1,0,1,0,1,1) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,1))
12123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && BITS4(0,1,0,0) == (INSN(19,16) & BITS4(1,1,1,0))
12124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && BITS4(1,0,1,0) == INSN(11,8)
12125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && BITS4(0,1,0,0) == (INSN(7,4) & BITS4(0,1,0,1))) {
12126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt bZ = (insn28 >> 16) & 1;
12127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt bN = (insn28 >> 7) & 1;
12128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt bD = (insn28 >> 22) & 1;
12129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt bM = (insn28 >> 5) & 1;
12130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt fD = (INSN(15,12) << 1) | bD;
12131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt fM = (INSN(3,0) << 1) | bM;
12132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (bZ && (INSN(3,0) != 0 || (INSN(7,4) & 3) != 0)) {
12133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* does not decode; fall through */
12134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else {
12135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp argL = newTemp(Ity_F64);
12136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp argR = newTemp(Ity_F64);
12137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp irRes = newTemp(Ity_I32);
12138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign(argL, unop(Iop_F32toF64, getFReg(fD)));
12140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign(argR, bZ ? IRExpr_Const(IRConst_F64i(0))
12141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         : unop(Iop_F32toF64, getFReg(fM)));
12142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign(irRes, binop(Iop_CmpF64, mkexpr(argL), mkexpr(argR)));
12143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp nzcv     = IRTemp_INVALID;
12145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp oldFPSCR = newTemp(Ity_I32);
12146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp newFPSCR = newTemp(Ity_I32);
12147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* This is where the fun starts.  We have to convert 'irRes'
12149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            from an IR-convention return result (IRCmpF64Result) to an
12150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ARM-encoded (N,Z,C,V) group.  The final result is in the
12151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            bottom 4 bits of 'nzcv'. */
12152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Map compare result from IR to ARM(nzcv) */
12153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /*
12154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            FP cmp result | IR   | ARM(nzcv)
12155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            --------------------------------
12156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            UN              0x45   0011
12157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            LT              0x01   1000
12158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            GT              0x00   0010
12159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            EQ              0x40   0110
12160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         */
12161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         nzcv = mk_convert_IRCmpF64Result_to_NZCV(irRes);
12162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* And update FPSCR accordingly */
12164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign(oldFPSCR, IRExpr_Get(OFFB_FPSCR, Ity_I32));
12165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign(newFPSCR,
12166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                binop(Iop_Or32,
12167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      binop(Iop_And32, mkexpr(oldFPSCR), mkU32(0x0FFFFFFF)),
12168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      binop(Iop_Shl32, mkexpr(nzcv), mkU8(28))));
12169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putMiscReg32(OFFB_FPSCR, mkexpr(newFPSCR), condT);
12171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (bZ) {
12173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            DIP("fcmpz%ss%s s%u\n", bN ? "e" : "", nCC(conq), fD);
12174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
12175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            DIP("fcmp%ss%s s%u, s%u\n", bN ? "e" : "",
12176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                nCC(conq), fD, fM);
12177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
12178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto decode_success_vfp;
12179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
12180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* fall through */
12181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
12182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* --------------------- unary (S) --------------------- */
12184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (BITS8(1,1,1,0,1,0,1,1) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,1))
12185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && BITS4(0,0,0,0) == (INSN(19,16) & BITS4(1,1,1,0))
12186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && BITS4(1,0,1,0) == INSN(11,8)
12187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && BITS4(0,1,0,0) == (INSN(7,4) & BITS4(0,1,0,1))) {
12188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt bD = (insn28 >> 22) & 1;
12189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt bM = (insn28 >> 5) & 1;
12190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt fD  = (INSN(15,12) << 1) | bD;
12191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt fM  = (INSN(3,0) << 1) | bM;
12192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt b16 = (insn28 >> 16) & 1;
12193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt b7  = (insn28 >> 7) & 1;
12194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /**/ if (b16 == 0 && b7 == 0) {
12195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         // FCPYS
12196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putFReg(fD, getFReg(fM), condT);
12197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("fcpys%s s%u, s%u\n", nCC(conq), fD, fM);
12198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto decode_success_vfp;
12199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
12200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      else if (b16 == 0 && b7 == 1) {
12201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         // FABSS
12202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putFReg(fD, unop(Iop_AbsF32, getFReg(fM)), condT);
12203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("fabss%s s%u, s%u\n", nCC(conq), fD, fM);
12204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto decode_success_vfp;
12205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
12206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      else if (b16 == 1 && b7 == 0) {
12207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         // FNEGS
12208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putFReg(fD, unop(Iop_NegF32, getFReg(fM)), condT);
12209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("fnegs%s s%u, s%u\n", nCC(conq), fD, fM);
12210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto decode_success_vfp;
12211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
12212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      else if (b16 == 1 && b7 == 1) {
12213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         // FSQRTS
12214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRExpr* rm = get_FAKE_roundingmode(); /* XXXROUNDINGFIXME */
12215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putFReg(fD, binop(Iop_SqrtF32, rm, getFReg(fM)), condT);
12216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("fsqrts%s s%u, s%u\n", nCC(conq), fD, fM);
12217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto decode_success_vfp;
12218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
12219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      else
12220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(0);
12221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* fall through */
12223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
12224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* ----------------- I <-> S conversions ----------------- */
12226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // F{S,U}ITOS fD, fM
12228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* These are more complex than FSITOD/FUITOD.  In the D cases, a 32
12229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      bit int will always fit within the 53 bit mantissa, so there's
12230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      no possibility of a loss of precision, but that's obviously not
12231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      the case here.  Hence this case possibly requires rounding, and
12232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      so it drags in the current rounding mode. */
12233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (BITS8(1,1,1,0,1,0,1,1) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,1))
12234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && BITS4(1,0,0,0) == INSN(19,16)
12235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && BITS4(1,0,1,0) == (INSN(11,8) & BITS4(1,1,1,0))
12236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && BITS4(0,1,0,0) == (INSN(7,4) & BITS4(0,1,0,1))) {
12237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt bM    = (insn28 >> 5) & 1;
12238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt bD    = (insn28 >> 22) & 1;
12239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt fM    = (INSN(3,0) << 1) | bM;
12240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt fD    = (INSN(15,12) << 1) | bD;
12241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt syned = (insn28 >> 7) & 1;
12242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp rmode = newTemp(Ity_I32);
12243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign(rmode, mkexpr(mk_get_IR_rounding_mode()));
12244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (syned) {
12245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         // FSITOS
12246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putFReg(fD, binop(Iop_F64toF32,
12247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           mkexpr(rmode),
12248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           unop(Iop_I32StoF64,
12249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                unop(Iop_ReinterpF32asI32, getFReg(fM)))),
12250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 condT);
12251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("fsitos%s s%u, s%u\n", nCC(conq), fD, fM);
12252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else {
12253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         // FUITOS
12254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putFReg(fD, binop(Iop_F64toF32,
12255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           mkexpr(rmode),
12256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           unop(Iop_I32UtoF64,
12257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                unop(Iop_ReinterpF32asI32, getFReg(fM)))),
12258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 condT);
12259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("fuitos%s s%u, s%u\n", nCC(conq), fD, fM);
12260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
12261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      goto decode_success_vfp;
12262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
12263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // FTO{S,U}IS fD, fM
12265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (BITS8(1,1,1,0,1,0,1,1) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,1))
12266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && BITS4(1,1,0,0) == (INSN(19,16) & BITS4(1,1,1,0))
12267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && BITS4(1,0,1,0) == INSN(11,8)
12268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && BITS4(0,1,0,0) == (INSN(7,4) & BITS4(0,1,0,1))) {
12269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt   bM    = (insn28 >> 5) & 1;
12270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt   bD    = (insn28 >> 22) & 1;
12271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt   fD    = (INSN(15,12) << 1) | bD;
12272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt   fM    = (INSN(3,0) << 1) | bM;
12273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt   bZ    = (insn28 >> 7) & 1;
12274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt   syned = (insn28 >> 16) & 1;
12275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp rmode = newTemp(Ity_I32);
12276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign(rmode, bZ ? mkU32(Irrm_ZERO)
12277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       : mkexpr(mk_get_IR_rounding_mode()));
12278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (syned) {
12279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         // FTOSIS
12280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putFReg(fD, unop(Iop_ReinterpI32asF32,
12281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          binop(Iop_F64toI32S, mkexpr(rmode),
12282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                unop(Iop_F32toF64, getFReg(fM)))),
12283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 condT);
12284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("ftosi%ss%s s%u, d%u\n", bZ ? "z" : "",
12285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             nCC(conq), fD, fM);
12286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto decode_success_vfp;
12287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else {
12288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         // FTOUIS
12289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putFReg(fD, unop(Iop_ReinterpI32asF32,
12290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          binop(Iop_F64toI32U, mkexpr(rmode),
12291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                unop(Iop_F32toF64, getFReg(fM)))),
12292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 condT);
12293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("ftoui%ss%s s%u, d%u\n", bZ ? "z" : "",
12294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             nCC(conq), fD, fM);
12295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto decode_success_vfp;
12296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
12297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
12298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* ----------------- S <-> D conversions ----------------- */
12300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // FCVTDS
12302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (BITS8(1,1,1,0,1,0,1,1) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,1))
12303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && BITS4(0,1,1,1) == INSN(19,16)
12304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && BITS4(1,0,1,0) == INSN(11,8)
12305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && BITS4(1,1,0,0) == (INSN(7,4) & BITS4(1,1,0,1))) {
12306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt dD = INSN(15,12) | (INSN(22,22) << 4);
12307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt bM = (insn28 >> 5) & 1;
12308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt fM = (INSN(3,0) << 1) | bM;
12309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putDReg(dD, unop(Iop_F32toF64, getFReg(fM)), condT);
12310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("fcvtds%s d%u, s%u\n", nCC(conq), dD, fM);
12311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      goto decode_success_vfp;
12312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
12313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // FCVTSD
12315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (BITS8(1,1,1,0,1,0,1,1) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,1))
12316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && BITS4(0,1,1,1) == INSN(19,16)
12317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && BITS4(1,0,1,1) == INSN(11,8)
12318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && BITS4(1,1,0,0) == (INSN(7,4) & BITS4(1,1,0,1))) {
12319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt   bD    = (insn28 >> 22) & 1;
12320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt   fD    = (INSN(15,12) << 1) | bD;
12321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt   dM    = INSN(3,0) | (INSN(5,5) << 4);
12322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp rmode = newTemp(Ity_I32);
12323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign(rmode, mkexpr(mk_get_IR_rounding_mode()));
12324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putFReg(fD, binop(Iop_F64toF32, mkexpr(rmode), getDReg(dM)),
12325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  condT);
12326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("fcvtsd%s s%u, d%u\n", nCC(conq), fD, dM);
12327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      goto decode_success_vfp;
12328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
12329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12330663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* --------------- VCVT fixed<->floating, VFP --------------- */
12331663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /*          31   27   23   19   15 11   7    3
12332663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                 28   24   20   16 12    8    4    0
12333663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
12334663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               cond 1110 1D11 1p1U Vd 101f x1i0 imm4
12335663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
12336663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      VCVT<c>.<Td>.F64 <Dd>, <Dd>, #fbits
12337663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      VCVT<c>.<Td>.F32 <Dd>, <Dd>, #fbits
12338663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      VCVT<c>.F64.<Td> <Dd>, <Dd>, #fbits
12339663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      VCVT<c>.F32.<Td> <Dd>, <Dd>, #fbits
12340663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      are of this form.  We only handle a subset of the cases though.
12341663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   */
12342663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (BITS8(1,1,1,0,1,0,1,1) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,1))
12343663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng       && BITS4(1,0,1,0) == (INSN(19,16) & BITS4(1,0,1,0))
12344663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng       && BITS3(1,0,1) == INSN(11,9)
12345663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng       && BITS3(1,0,0) == (INSN(6,4) & BITS3(1,0,1))) {
12346663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      UInt bD   = INSN(22,22);
12347663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      UInt bOP  = INSN(18,18);
12348663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      UInt bU   = INSN(16,16);
12349663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      UInt Vd   = INSN(15,12);
12350663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      UInt bSF  = INSN(8,8);
12351663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      UInt bSX  = INSN(7,7);
12352663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      UInt bI   = INSN(5,5);
12353663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      UInt imm4 = INSN(3,0);
12354663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      Bool to_fixed = bOP == 1;
12355663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      Bool dp_op    = bSF == 1;
12356663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      Bool unsyned = bU == 1;
12357663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      UInt size = bSX == 0 ? 16 : 32;
12358663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      Int frac_bits = size - ((imm4 << 1) | bI);
12359663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      UInt d = dp_op  ? ((bD << 4) | Vd)  : ((Vd << 1) | bD);
123600545291109e6df688a3bae37e0de494f044a81edBen Cheng      if (frac_bits >= 1 && frac_bits <= 32 && !to_fixed && size == 32) {
123610545291109e6df688a3bae37e0de494f044a81edBen Cheng         /* dp_op == 0 : VCVT.F32.{S,U}32 S[d], S[d], #frac_bits */
123620545291109e6df688a3bae37e0de494f044a81edBen Cheng         /* dp_op == 1 : VCVT.F64.{S,U}32 D[d], D[d], #frac_bits */
12363663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* This generates really horrible code.  We could potentially
12364663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            do much better. */
12365663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp rmode = newTemp(Ity_I32);
12366663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         assign(rmode, mkU32(Irrm_NEAREST)); // rmode that this insn is defd to use
12367663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp src32 = newTemp(Ity_I32);
12368b14a1266f5cc4544b41db37b33ff37d5071cee3bBen Cheng         if (dp_op == 0) {
12369b14a1266f5cc4544b41db37b33ff37d5071cee3bBen Cheng            assign(src32,  unop(Iop_ReinterpF32asI32, getFReg(d)));
12370b14a1266f5cc4544b41db37b33ff37d5071cee3bBen Cheng         } else {
12371b14a1266f5cc4544b41db37b33ff37d5071cee3bBen Cheng            /* Example code sequence of using vcvt.f64.s32. The s32 value is
12372b14a1266f5cc4544b41db37b33ff37d5071cee3bBen Cheng               initialized in s14 but loaded via d7 (s14 is the low half of
12373b14a1266f5cc4544b41db37b33ff37d5071cee3bBen Cheng               d7), so we need to decode the register using getDReg instead of
12374b14a1266f5cc4544b41db37b33ff37d5071cee3bBen Cheng               getFReg. Since the conversion size is from s32 to f64, we also
12375b14a1266f5cc4544b41db37b33ff37d5071cee3bBen Cheng               need to explicitly extract the low half of i64 here.
12376b14a1266f5cc4544b41db37b33ff37d5071cee3bBen Cheng
12377b14a1266f5cc4544b41db37b33ff37d5071cee3bBen Cheng               81a0:       ee07 2a10       vmov            s14, r2
12378b14a1266f5cc4544b41db37b33ff37d5071cee3bBen Cheng               81a4:       eeba 7bef       vcvt.f64.s32    d7, d7, #1
12379b14a1266f5cc4544b41db37b33ff37d5071cee3bBen Cheng             */
12380b14a1266f5cc4544b41db37b33ff37d5071cee3bBen Cheng            IRTemp src64 = newTemp(Ity_I64);
12381b14a1266f5cc4544b41db37b33ff37d5071cee3bBen Cheng            assign(src64,  unop(Iop_ReinterpF64asI64, getDReg(d)));
12382b14a1266f5cc4544b41db37b33ff37d5071cee3bBen Cheng            assign(src32, unop(Iop_64to32, mkexpr(src64)));
12383b14a1266f5cc4544b41db37b33ff37d5071cee3bBen Cheng         }
12384663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRExpr* as_F64 = unop( unsyned ? Iop_I32UtoF64 : Iop_I32StoF64,
12385663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                mkexpr(src32 ) );
12386663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRTemp scale = newTemp(Ity_F64);
12387663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         assign(scale, unop(Iop_I32UtoF64, mkU32( 1 << (frac_bits-1) )));
12388663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRExpr* rm     = mkU32(Irrm_NEAREST);
12389663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRExpr* resF64 = triop(Iop_DivF64,
12390663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                rm, as_F64,
12391663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                triop(Iop_AddF64, rm, mkexpr(scale), mkexpr(scale)));
123920545291109e6df688a3bae37e0de494f044a81edBen Cheng         if (dp_op == 0) {
123930545291109e6df688a3bae37e0de494f044a81edBen Cheng            IRExpr* resF32 = binop(Iop_F64toF32, mkexpr(rmode), resF64);
123940545291109e6df688a3bae37e0de494f044a81edBen Cheng            putFReg(d, resF32, condT);
123950545291109e6df688a3bae37e0de494f044a81edBen Cheng            DIP("vcvt.f32.%c32, s%u, s%u, #%d\n",
123960545291109e6df688a3bae37e0de494f044a81edBen Cheng                unsyned ? 'u' : 's', d, d, frac_bits);
123970545291109e6df688a3bae37e0de494f044a81edBen Cheng         } else {
123980545291109e6df688a3bae37e0de494f044a81edBen Cheng            putDReg(d, resF64, condT);
123990545291109e6df688a3bae37e0de494f044a81edBen Cheng            DIP("vcvt.f64.%c32, d%u, d%u, #%d\n",
124000545291109e6df688a3bae37e0de494f044a81edBen Cheng                unsyned ? 'u' : 's', d, d, frac_bits);
124010545291109e6df688a3bae37e0de494f044a81edBen Cheng         }
12402663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success_vfp;
12403663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
12404663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* fall through */
12405663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
12406663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
12407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* FAILURE */
12408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return False;
12409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  decode_success_vfp:
12411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Check that any accepted insn really is a CP10 or CP11 insn, iow,
12412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assert that we aren't accepting, in this fn, insns that actually
12413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      should be handled somewhere else. */
12414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(INSN(11,9) == BITS3(1,0,1)); // 11:8 = 1010 or 1011
12415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return True;
12416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  undef INSN
12418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
12419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
12422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Instructions in NV (never) space                     ---*/
12423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
12424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* ARM only */
12426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Translate a NV space instruction.  If successful, returns True and
12427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   *dres may or may not be updated.  If failure, returns False and
12428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   doesn't change *dres nor create any IR.
12429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Note that all NEON instructions (in ARM mode) are handled through
12431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   here, since they are all in NV space.
12432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
12433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool decode_NV_instruction ( /*MOD*/DisResult* dres,
12434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                    VexArchInfo* archinfo,
12435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                    UInt insn )
12436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
12437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  define INSN(_bMax,_bMin)  SLICE_UInt(insn, (_bMax), (_bMin))
12438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  define INSN_COND          SLICE_UInt(insn, 31, 28)
12439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   HChar dis_buf[128];
12441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // Should only be called for NV instructions
12443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(BITS4(1,1,1,1) == INSN_COND);
12444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* ------------------------ pld ------------------------ */
12446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (BITS8(0,1,0,1, 0, 1,0,1) == (INSN(27,20) & BITS8(1,1,1,1,0,1,1,1))
12447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && BITS4(1,1,1,1) == INSN(15,12)) {
12448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt rN    = INSN(19,16);
12449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt imm12 = INSN(11,0);
12450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt bU    = INSN(23,23);
12451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("pld [r%u, #%c%u]\n", rN, bU ? '+' : '-', imm12);
12452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return True;
12453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
12454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (BITS8(0,1,1,1, 0, 1,0,1) == (INSN(27,20) & BITS8(1,1,1,1,0,1,1,1))
12456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && BITS4(1,1,1,1) == INSN(15,12)
12457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && 0 == INSN(4,4)) {
12458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt rN   = INSN(19,16);
12459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt rM   = INSN(3,0);
12460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt imm5 = INSN(11,7);
12461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt sh2  = INSN(6,5);
12462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt bU   = INSN(23,23);
12463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (rM != 15) {
12464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRExpr* eaE = mk_EA_reg_plusminus_shifted_reg(rN, bU, rM,
12465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                                       sh2, imm5, dis_buf);
12466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp eaT = newTemp(Ity_I32);
12467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Bind eaE to a temp merely for debugging-vex purposes, so we
12468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            can check it's a plausible decoding.  It will get removed
12469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            by iropt a little later on. */
12470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(eaE);
12471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign(eaT, eaE);
12472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("pld %s\n", dis_buf);
12473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return True;
12474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
12475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* fall through */
12476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
12477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* ------------------------ pli ------------------------ */
12479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (BITS8(0,1,0,0, 0, 1,0,1) == (INSN(27,20) & BITS8(1,1,1,1,0,1,1,1))
12480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && BITS4(1,1,1,1) == INSN(15,12)) {
12481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt rN    = INSN(19,16);
12482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt imm12 = INSN(11,0);
12483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt bU    = INSN(23,23);
12484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("pli [r%u, #%c%u]\n", rN, bU ? '+' : '-', imm12);
12485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return True;
12486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
12487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* --------------------- Interworking branches --------------------- */
12489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // BLX (1), viz, unconditional branch and link to R15+simm24
12491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // and set CPSR.T = 1, that is, switch to Thumb mode
12492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (INSN(31,25) == BITS7(1,1,1,1,1,0,1)) {
12493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt bitH   = INSN(24,24);
12494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Int  uimm24 = INSN(23,0);
12495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Int  simm24 = (((uimm24 << 8) >> 8) << 2) + (bitH << 1);
12496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Now this is a bit tricky.  Since we're decoding an ARM insn,
12497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         it is implies that CPSR.T == 0.  Hence the current insn's
12498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         address is guaranteed to be of the form X--(30)--X00.  So, no
12499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         need to mask any bits off it.  But need to set the lowest bit
12500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         to 1 to denote we're in Thumb mode after this, since
12501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         guest_R15T has CPSR.T as the lowest bit.  And we can't chase
12502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         into the call, so end the block at this point. */
12503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt dst = guest_R15_curr_instr_notENC + 8 + (simm24 | 1);
12504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putIRegA( 14, mkU32(guest_R15_curr_instr_notENC + 4),
12505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    IRTemp_INVALID/*because AL*/, Ijk_Boring );
12506663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      llPutIReg(15, mkU32(dst));
12507663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      dres->jk_StopHere = Ijk_Call;
12508663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      dres->whatNext    = Dis_StopHere;
12509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("blx 0x%x (and switch to Thumb mode)\n", dst - 1);
12510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return True;
12511ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
12512ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12513ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* ------------------- v7 barrier insns ------------------- */
12514ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (insn) {
12515ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0xF57FF06F: /* ISB */
12516ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         stmt( IRStmt_MBE(Imbe_Fence) );
12517ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("ISB\n");
12518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return True;
125191b891657a2208341cc71c68ae16eada0bee46d91Jeff Brown      case 0xF57FF04F: /* DSB sy */
125201b891657a2208341cc71c68ae16eada0bee46d91Jeff Brown      case 0xF57FF04E: /* DSB st */
125211b891657a2208341cc71c68ae16eada0bee46d91Jeff Brown      case 0xF57FF04B: /* DSB ish */
125221b891657a2208341cc71c68ae16eada0bee46d91Jeff Brown      case 0xF57FF04A: /* DSB ishst */
125231b891657a2208341cc71c68ae16eada0bee46d91Jeff Brown      case 0xF57FF047: /* DSB nsh */
125241b891657a2208341cc71c68ae16eada0bee46d91Jeff Brown      case 0xF57FF046: /* DSB nshst */
125251b891657a2208341cc71c68ae16eada0bee46d91Jeff Brown      case 0xF57FF043: /* DSB osh */
125261b891657a2208341cc71c68ae16eada0bee46d91Jeff Brown      case 0xF57FF042: /* DSB oshst */
12527ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         stmt( IRStmt_MBE(Imbe_Fence) );
12528ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("DSB\n");
12529ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return True;
125301b891657a2208341cc71c68ae16eada0bee46d91Jeff Brown      case 0xF57FF05F: /* DMB sy */
125311b891657a2208341cc71c68ae16eada0bee46d91Jeff Brown      case 0xF57FF05E: /* DMB st */
125321b891657a2208341cc71c68ae16eada0bee46d91Jeff Brown      case 0xF57FF05B: /* DMB ish */
125331b891657a2208341cc71c68ae16eada0bee46d91Jeff Brown      case 0xF57FF05A: /* DMB ishst */
125341b891657a2208341cc71c68ae16eada0bee46d91Jeff Brown      case 0xF57FF057: /* DMB nsh */
125351b891657a2208341cc71c68ae16eada0bee46d91Jeff Brown      case 0xF57FF056: /* DMB nshst */
125361b891657a2208341cc71c68ae16eada0bee46d91Jeff Brown      case 0xF57FF053: /* DMB osh */
125371b891657a2208341cc71c68ae16eada0bee46d91Jeff Brown      case 0xF57FF052: /* DMB oshst */
12538ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         stmt( IRStmt_MBE(Imbe_Fence) );
12539ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("DMB\n");
12540ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return True;
12541ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
12542ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
12543ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
12544ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12545b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   /* ------------------- CLREX ------------------ */
12546b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   if (insn == 0xF57FF01F) {
12547b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      /* AFAICS, this simply cancels a (all?) reservations made by a
12548b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         (any?) preceding LDREX(es).  Arrange to hand it through to
12549b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         the back end. */
12550b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      stmt( IRStmt_MBE(Imbe_CancelReservation) );
12551b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      DIP("clrex\n");
12552b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      return True;
12553b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   }
12554b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
12555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* ------------------- NEON ------------------- */
12556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (archinfo->hwcaps & VEX_HWCAPS_ARM_NEON) {
12557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Bool ok_neon = decode_NEON_instruction(
12558ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        dres, insn, IRTemp_INVALID/*unconditional*/,
12559ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        False/*!isT*/
12560ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     );
12561ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (ok_neon)
12562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return True;
12563ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
12564ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12565ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // unrecognised
12566ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return False;
12567ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12568ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  undef INSN_COND
12569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  undef INSN
12570ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
12571ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12572ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12573ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
12574ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Disassemble a single ARM instruction                 ---*/
12575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
12576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Disassemble a single ARM instruction into IR.  The instruction is
12578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   located in host memory at guest_instr, and has (decoded) guest IP
12579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   of guest_R15_curr_instr_notENC, which will have been set before the
12580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   call here. */
12581ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12582ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
12583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownDisResult disInstr_ARM_WRK (
12584ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             Bool         (*resteerOkFn) ( /*opaque*/void*, Addr64 ),
12585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             Bool         resteerCisOk,
12586ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             void*        callback_opaque,
12587ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             UChar*       guest_instr,
12588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             VexArchInfo* archinfo,
12589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             VexAbiInfo*  abiinfo
12590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          )
12591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
12592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // A macro to fish bits out of 'insn'.
12593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  define INSN(_bMax,_bMin)  SLICE_UInt(insn, (_bMax), (_bMin))
12594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  define INSN_COND          SLICE_UInt(insn, 31, 28)
12595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   DisResult dres;
12597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt      insn;
12598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //Bool      allow_VFP = False;
12599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //UInt      hwcaps = archinfo->hwcaps;
12600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp    condT; /* :: Ity_I32 */
12601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt      summary;
12602ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   HChar     dis_buf[128];  // big enough to hold LDMIA etc text
12603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* What insn variants are we supporting today? */
12605ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //allow_VFP  = (0 != (hwcaps & VEX_HWCAPS_ARM_VFP));
12606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // etc etc
12607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12608ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Set result defaults. */
12609663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   dres.whatNext    = Dis_Continue;
12610663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   dres.len         = 4;
12611663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   dres.continueAt  = 0;
12612663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   dres.jk_StopHere = Ijk_INVALID;
12613ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12614ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Set default actions for post-insn handling of writes to r15, if
12615ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      required. */
12616ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   r15written = False;
12617ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   r15guard   = IRTemp_INVALID; /* unconditional */
12618ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   r15kind    = Ijk_Boring;
12619ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12620ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* At least this is simple on ARM: insns are all 4 bytes long, and
12621ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      4-aligned.  So just fish the whole thing out of memory right now
12622ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      and have done. */
12623ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   insn = getUIntLittleEndianly( guest_instr );
12624ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12625ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (0) vex_printf("insn: 0x%x\n", insn);
12626ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12627ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   DIP("\t(arm) 0x%x:  ", (UInt)guest_R15_curr_instr_notENC);
12628ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12629ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(0 == (guest_R15_curr_instr_notENC & 3));
12630ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* ----------------------------------------------------------- */
12632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12633ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Spot "Special" instructions (see comment at top of file). */
12634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   {
12635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UChar* code = (UChar*)guest_instr;
12636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Spot the 16-byte preamble:
12637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12638ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         e1a0c1ec  mov r12, r12, ROR #3
12639ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         e1a0c6ec  mov r12, r12, ROR #13
12640ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         e1a0ceec  mov r12, r12, ROR #29
12641ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         e1a0c9ec  mov r12, r12, ROR #19
12642ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      */
12643ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt word1 = 0xE1A0C1EC;
12644ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt word2 = 0xE1A0C6EC;
12645ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt word3 = 0xE1A0CEEC;
12646ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt word4 = 0xE1A0C9EC;
12647ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (getUIntLittleEndianly(code+ 0) == word1 &&
12648ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          getUIntLittleEndianly(code+ 4) == word2 &&
12649ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          getUIntLittleEndianly(code+ 8) == word3 &&
12650ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          getUIntLittleEndianly(code+12) == word4) {
12651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Got a "Special" instruction preamble.  Which one is it? */
12652ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (getUIntLittleEndianly(code+16) == 0xE18AA00A
12653ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                               /* orr r10,r10,r10 */) {
12654ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* R3 = client_request ( R4 ) */
12655ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            DIP("r3 = client_request ( %%r4 )\n");
12656663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            llPutIReg(15, mkU32( guest_R15_curr_instr_notENC + 20 ));
12657663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            dres.jk_StopHere = Ijk_ClientReq;
12658663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            dres.whatNext    = Dis_StopHere;
12659ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto decode_success;
12660ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
12661ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         else
12662ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (getUIntLittleEndianly(code+16) == 0xE18BB00B
12663ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                               /* orr r11,r11,r11 */) {
12664ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* R3 = guest_NRADDR */
12665ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            DIP("r3 = guest_NRADDR\n");
12666ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            dres.len = 20;
12667ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            llPutIReg(3, IRExpr_Get( OFFB_NRADDR, Ity_I32 ));
12668ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto decode_success;
12669ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
12670ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         else
12671ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (getUIntLittleEndianly(code+16) == 0xE18CC00C
12672ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                               /* orr r12,r12,r12 */) {
12673ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /*  branch-and-link-to-noredir R4 */
12674ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            DIP("branch-and-link-to-noredir r4\n");
12675ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            llPutIReg(14, mkU32( guest_R15_curr_instr_notENC + 20) );
12676663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            llPutIReg(15, llGetIReg(4));
12677663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            dres.jk_StopHere = Ijk_NoRedir;
12678663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            dres.whatNext    = Dis_StopHere;
12679ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto decode_success;
12680ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
12681ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* We don't know what it is.  Set opc1/opc2 so decode_failure
12682ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            can print the insn following the Special-insn preamble. */
12683ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         insn = getUIntLittleEndianly(code+16);
12684ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto decode_failure;
12685ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /*NOTREACHED*/
12686ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
12687ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12688ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
12689ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12690ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* ----------------------------------------------------------- */
12691ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12692ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Main ARM instruction decoder starts here. */
12693ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12694ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Deal with the condition.  Strategy is to merely generate a
12695ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      condition temporary at this point (or IRTemp_INVALID, meaning
12696ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      unconditional).  We leave it to lower-level instruction decoders
12697ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      to decide whether they can generate straight-line code, or
12698ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      whether they must generate a side exit before the instruction.
12699ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      condT :: Ity_I32 and is always either zero or one. */
12700ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   condT = IRTemp_INVALID;
12701ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch ( (ARMCondcode)INSN_COND ) {
12702ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case ARMCondNV: {
12703ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         // Illegal instruction prior to v5 (see ARM ARM A3-5), but
12704ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         // some cases are acceptable
12705ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         Bool ok = decode_NV_instruction(&dres, archinfo, insn);
12706ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (ok)
12707ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto decode_success;
12708ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         else
12709ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto decode_failure;
12710ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
12711ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case ARMCondAL: // Always executed
12712ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
12713ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case ARMCondEQ: case ARMCondNE: case ARMCondHS: case ARMCondLO:
12714ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case ARMCondMI: case ARMCondPL: case ARMCondVS: case ARMCondVC:
12715ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case ARMCondHI: case ARMCondLS: case ARMCondGE: case ARMCondLT:
12716ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case ARMCondGT: case ARMCondLE:
12717ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         condT = newTemp(Ity_I32);
12718ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( condT, mk_armg_calculate_condition( INSN_COND ));
12719ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
12720ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
12721ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12722ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* ----------------------------------------------------------- */
12723ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* -- ARMv5 integer instructions                            -- */
12724ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* ----------------------------------------------------------- */
12725ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12726ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* ---------------- Data processing ops ------------------- */
12727ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12728ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (0 == (INSN(27,20) & BITS8(1,1,0,0,0,0,0,0))
12729ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && !(INSN(25,25) == 0 && INSN(7,7) == 1 && INSN(4,4) == 1)) {
12730ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp  shop = IRTemp_INVALID; /* shifter operand */
12731ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp  shco = IRTemp_INVALID; /* shifter carry out */
12732ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt    rD   = (insn >> 12) & 0xF; /* 15:12 */
12733ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt    rN   = (insn >> 16) & 0xF; /* 19:16 */
12734ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt    bitS = (insn >> 20) & 1; /* 20:20 */
12735ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp  rNt  = IRTemp_INVALID;
12736ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp  res  = IRTemp_INVALID;
12737ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp  oldV = IRTemp_INVALID;
12738ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp  oldC = IRTemp_INVALID;
12739ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HChar*  name = NULL;
12740ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IROp    op   = Iop_INVALID;
12741ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Bool    ok;
12742ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12743ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch (INSN(24,21)) {
12744ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12745ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* --------- ADD, SUB, AND, OR --------- */
12746ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case BITS4(0,1,0,0): /* ADD:  Rd = Rn + shifter_operand */
12747ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            name = "add"; op = Iop_Add32; goto rd_eq_rn_op_SO;
12748ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case BITS4(0,0,1,0): /* SUB:  Rd = Rn - shifter_operand */
12749ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            name = "sub"; op = Iop_Sub32; goto rd_eq_rn_op_SO;
12750ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case BITS4(0,0,1,1): /* RSB:  Rd = shifter_operand - Rn */
12751ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            name = "rsb"; op = Iop_Sub32; goto rd_eq_rn_op_SO;
12752ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case BITS4(0,0,0,0): /* AND:  Rd = Rn & shifter_operand */
12753ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            name = "and"; op = Iop_And32; goto rd_eq_rn_op_SO;
12754ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case BITS4(1,1,0,0): /* OR:   Rd = Rn | shifter_operand */
12755ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            name = "orr"; op = Iop_Or32; goto rd_eq_rn_op_SO;
12756ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case BITS4(0,0,0,1): /* EOR:  Rd = Rn ^ shifter_operand */
12757ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            name = "eor"; op = Iop_Xor32; goto rd_eq_rn_op_SO;
12758ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case BITS4(1,1,1,0): /* BIC:  Rd = Rn & ~shifter_operand */
12759ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            name = "bic"; op = Iop_And32; goto rd_eq_rn_op_SO;
12760ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         rd_eq_rn_op_SO: {
12761ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            Bool isRSB = False;
12762ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            Bool isBIC = False;
12763ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            switch (INSN(24,21)) {
12764ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               case BITS4(0,0,1,1):
12765ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  vassert(op == Iop_Sub32); isRSB = True; break;
12766ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               case BITS4(1,1,1,0):
12767ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  vassert(op == Iop_And32); isBIC = True; break;
12768ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               default:
12769ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  break;
12770ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
12771ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            rNt = newTemp(Ity_I32);
12772ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            assign(rNt, getIRegA(rN));
12773ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ok = mk_shifter_operand(
12774ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    INSN(25,25), INSN(11,0),
12775ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    &shop, bitS ? &shco : NULL, dis_buf
12776ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 );
12777ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (!ok)
12778ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
12779ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            res = newTemp(Ity_I32);
12780ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            // compute the main result
12781ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (isRSB) {
12782ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               // reverse-subtract: shifter_operand - Rn
12783ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               vassert(op == Iop_Sub32);
12784ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               assign(res, binop(op, mkexpr(shop), mkexpr(rNt)) );
12785ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else if (isBIC) {
12786ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               // andn: shifter_operand & ~Rn
12787ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               vassert(op == Iop_And32);
12788ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               assign(res, binop(op, mkexpr(rNt),
12789ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                     unop(Iop_Not32, mkexpr(shop))) );
12790ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else {
12791ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               // normal: Rn op shifter_operand
12792ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               assign(res, binop(op, mkexpr(rNt), mkexpr(shop)) );
12793ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
12794ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            // but don't commit it until after we've finished
12795ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            // all necessary reads from the guest state
12796ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (bitS
12797ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                && (op == Iop_And32 || op == Iop_Or32 || op == Iop_Xor32)) {
12798ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               oldV = newTemp(Ity_I32);
12799ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               assign( oldV, mk_armg_calculate_flag_v() );
12800ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
12801ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            // can't safely read guest state after here
12802ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            // now safe to put the main result
12803ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            putIRegA( rD, mkexpr(res), condT, Ijk_Boring );
12804ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            // XXXX!! not safe to read any guest state after
12805ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            // this point (I think the code below doesn't do that).
12806ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (!bitS)
12807ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               vassert(shco == IRTemp_INVALID);
12808ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* Update the flags thunk if necessary */
12809ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (bitS) {
12810ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               vassert(shco != IRTemp_INVALID);
12811ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               switch (op) {
12812ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case Iop_Add32:
12813ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     setFlags_D1_D2( ARMG_CC_OP_ADD, rNt, shop, condT );
12814ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     break;
12815ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case Iop_Sub32:
12816ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     if (isRSB) {
12817ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        setFlags_D1_D2( ARMG_CC_OP_SUB, shop, rNt, condT );
12818ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     } else {
12819ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        setFlags_D1_D2( ARMG_CC_OP_SUB, rNt, shop, condT );
12820ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     }
12821ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     break;
12822ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case Iop_And32: /* BIC and AND set the flags the same */
12823ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case Iop_Or32:
12824ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case Iop_Xor32:
12825ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     // oldV has been read just above
12826ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     setFlags_D1_D2_ND( ARMG_CC_OP_LOGIC,
12827ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                        res, shco, oldV, condT );
12828ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     break;
12829ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  default:
12830ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     vassert(0);
12831ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               }
12832ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
12833ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            DIP("%s%s%s r%u, r%u, %s\n",
12834ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                name, nCC(INSN_COND), bitS ? "s" : "", rD, rN, dis_buf );
12835ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto decode_success;
12836ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
12837ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12838ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* --------- MOV, MVN --------- */
12839ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case BITS4(1,1,0,1):   /* MOV: Rd = shifter_operand */
12840ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case BITS4(1,1,1,1): { /* MVN: Rd = not(shifter_operand) */
12841ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            Bool isMVN = INSN(24,21) == BITS4(1,1,1,1);
12842b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            IRTemp jk = Ijk_Boring;
12843ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (rN != 0)
12844ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break; /* rN must be zero */
12845ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ok = mk_shifter_operand(
12846ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    INSN(25,25), INSN(11,0),
12847ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    &shop, bitS ? &shco : NULL, dis_buf
12848ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 );
12849ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (!ok)
12850ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
12851ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            res = newTemp(Ity_I32);
12852ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            assign( res, isMVN ? unop(Iop_Not32, mkexpr(shop))
12853ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               : mkexpr(shop) );
12854ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (bitS) {
12855ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               vassert(shco != IRTemp_INVALID);
12856ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               oldV = newTemp(Ity_I32);
12857ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               assign( oldV, mk_armg_calculate_flag_v() );
12858ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else {
12859ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               vassert(shco == IRTemp_INVALID);
12860ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
12861b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            /* According to the Cortex A8 TRM Sec. 5.2.1, MOV PC, r14 is a
12862b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                return for purposes of branch prediction. */
12863b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            if (!isMVN && INSN(11,0) == 14) {
12864b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov              jk = Ijk_Ret;
12865b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            }
12866ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            // can't safely read guest state after here
12867b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            putIRegA( rD, mkexpr(res), condT, jk );
12868ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* Update the flags thunk if necessary */
12869ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (bitS) {
12870ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               setFlags_D1_D2_ND( ARMG_CC_OP_LOGIC,
12871ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                  res, shco, oldV, condT );
12872ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
12873ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            DIP("%s%s%s r%u, %s\n",
12874ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                isMVN ? "mvn" : "mov",
12875ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                nCC(INSN_COND), bitS ? "s" : "", rD, dis_buf );
12876ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto decode_success;
12877ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
12878ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12879ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* --------- CMP --------- */
12880ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case BITS4(1,0,1,0):   /* CMP:  (void) Rn - shifter_operand */
12881ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case BITS4(1,0,1,1): { /* CMN:  (void) Rn + shifter_operand */
12882ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            Bool isCMN = INSN(24,21) == BITS4(1,0,1,1);
12883ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (rD != 0)
12884ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break; /* rD must be zero */
12885ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (bitS == 0)
12886ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break; /* if S (bit 20) is not set, it's not CMP/CMN */
12887ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            rNt = newTemp(Ity_I32);
12888ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            assign(rNt, getIRegA(rN));
12889ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ok = mk_shifter_operand(
12890ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    INSN(25,25), INSN(11,0),
12891ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    &shop, NULL, dis_buf
12892ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 );
12893ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (!ok)
12894ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
12895ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            // can't safely read guest state after here
12896ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* Update the flags thunk. */
12897ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            setFlags_D1_D2( isCMN ? ARMG_CC_OP_ADD : ARMG_CC_OP_SUB,
12898ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            rNt, shop, condT );
12899ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            DIP("%s%s r%u, %s\n",
12900ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                isCMN ? "cmn" : "cmp",
12901ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                nCC(INSN_COND), rN, dis_buf );
12902ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto decode_success;
12903ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
12904ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12905ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* --------- TST --------- */
12906ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case BITS4(1,0,0,0):   /* TST:  (void) Rn & shifter_operand */
12907ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case BITS4(1,0,0,1): { /* TEQ:  (void) Rn ^ shifter_operand */
12908ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            Bool isTEQ = INSN(24,21) == BITS4(1,0,0,1);
12909ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (rD != 0)
12910ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break; /* rD must be zero */
12911ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (bitS == 0)
12912ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break; /* if S (bit 20) is not set, it's not TST/TEQ */
12913ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            rNt = newTemp(Ity_I32);
12914ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            assign(rNt, getIRegA(rN));
12915ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ok = mk_shifter_operand(
12916ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    INSN(25,25), INSN(11,0),
12917ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    &shop, &shco, dis_buf
12918ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 );
12919ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (!ok)
12920ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
12921ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* Update the flags thunk. */
12922ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            res = newTemp(Ity_I32);
12923ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            assign( res, binop(isTEQ ? Iop_Xor32 : Iop_And32,
12924ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               mkexpr(rNt), mkexpr(shop)) );
12925ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            oldV = newTemp(Ity_I32);
12926ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            assign( oldV, mk_armg_calculate_flag_v() );
12927ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            // can't safely read guest state after here
12928ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            setFlags_D1_D2_ND( ARMG_CC_OP_LOGIC,
12929ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               res, shco, oldV, condT );
12930ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            DIP("%s%s r%u, %s\n",
12931ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                isTEQ ? "teq" : "tst",
12932ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                nCC(INSN_COND), rN, dis_buf );
12933ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto decode_success;
12934ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
12935ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12936ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* --------- ADC, SBC, RSC --------- */
12937ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case BITS4(0,1,0,1): /* ADC:  Rd = Rn + shifter_operand + oldC */
12938ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            name = "adc"; goto rd_eq_rn_op_SO_op_oldC;
12939ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case BITS4(0,1,1,0): /* SBC:  Rd = Rn - shifter_operand - (oldC ^ 1) */
12940ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            name = "sbc"; goto rd_eq_rn_op_SO_op_oldC;
12941ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case BITS4(0,1,1,1): /* RSC:  Rd = shifter_operand - Rn - (oldC ^ 1) */
12942ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            name = "rsc"; goto rd_eq_rn_op_SO_op_oldC;
12943ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         rd_eq_rn_op_SO_op_oldC: {
12944ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            // FIXME: shco isn't used for anything.  Get rid of it.
12945ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            rNt = newTemp(Ity_I32);
12946ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            assign(rNt, getIRegA(rN));
12947ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ok = mk_shifter_operand(
12948ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    INSN(25,25), INSN(11,0),
12949ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    &shop, bitS ? &shco : NULL, dis_buf
12950ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 );
12951ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (!ok)
12952ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
12953ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            oldC = newTemp(Ity_I32);
12954ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            assign( oldC, mk_armg_calculate_flag_c() );
12955ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            res = newTemp(Ity_I32);
12956ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            // compute the main result
12957ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            switch (INSN(24,21)) {
12958ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               case BITS4(0,1,0,1): /* ADC */
12959ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  assign(res,
12960ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         binop(Iop_Add32,
12961ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               binop(Iop_Add32, mkexpr(rNt), mkexpr(shop)),
12962ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               mkexpr(oldC) ));
12963ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  break;
12964ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               case BITS4(0,1,1,0): /* SBC */
12965ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  assign(res,
12966ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         binop(Iop_Sub32,
12967ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               binop(Iop_Sub32, mkexpr(rNt), mkexpr(shop)),
12968ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               binop(Iop_Xor32, mkexpr(oldC), mkU32(1)) ));
12969ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  break;
12970ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               case BITS4(0,1,1,1): /* RSC */
12971ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  assign(res,
12972ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         binop(Iop_Sub32,
12973ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               binop(Iop_Sub32, mkexpr(shop), mkexpr(rNt)),
12974ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               binop(Iop_Xor32, mkexpr(oldC), mkU32(1)) ));
12975ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  break;
12976ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               default:
12977ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  vassert(0);
12978ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
12979ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            // but don't commit it until after we've finished
12980ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            // all necessary reads from the guest state
12981ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            // now safe to put the main result
12982ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            putIRegA( rD, mkexpr(res), condT, Ijk_Boring );
12983ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            // XXXX!! not safe to read any guest state after
12984ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            // this point (I think the code below doesn't do that).
12985ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (!bitS)
12986ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               vassert(shco == IRTemp_INVALID);
12987ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* Update the flags thunk if necessary */
12988ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (bitS) {
12989ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               vassert(shco != IRTemp_INVALID);
12990ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               switch (INSN(24,21)) {
12991ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case BITS4(0,1,0,1): /* ADC */
12992ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     setFlags_D1_D2_ND( ARMG_CC_OP_ADC,
12993ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                        rNt, shop, oldC, condT );
12994ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     break;
12995ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case BITS4(0,1,1,0): /* SBC */
12996ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     setFlags_D1_D2_ND( ARMG_CC_OP_SBB,
12997ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                        rNt, shop, oldC, condT );
12998ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     break;
12999ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  case BITS4(0,1,1,1): /* RSC */
13000ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     setFlags_D1_D2_ND( ARMG_CC_OP_SBB,
13001ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                        shop, rNt, oldC, condT );
13002ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     break;
13003ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  default:
13004ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     vassert(0);
13005ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               }
13006ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
13007ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            DIP("%s%s%s r%u, r%u, %s\n",
13008ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                name, nCC(INSN_COND), bitS ? "s" : "", rD, rN, dis_buf );
13009ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto decode_success;
13010ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
13011ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13012ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* --------- ??? --------- */
13013ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         default:
13014ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
13015ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
13016ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } /* if (0 == (INSN(27,20) & BITS8(1,1,0,0,0,0,0,0)) */
13017ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13018ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* --------------------- Load/store (ubyte & word) -------- */
13019ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // LDR STR LDRB STRB
13020ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /*                 31   27   23   19 15 11    6   4 3  # highest bit
13021ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        28   24   20 16 12
13022ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      A5-20   1 | 16  cond 0101 UB0L Rn Rd imm12
13023ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      A5-22   1 | 32  cond 0111 UBOL Rn Rd imm5  sh2 0 Rm
13024ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      A5-24   2 | 16  cond 0101 UB1L Rn Rd imm12
13025ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      A5-26   2 | 32  cond 0111 UB1L Rn Rd imm5  sh2 0 Rm
13026ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      A5-28   3 | 16  cond 0100 UB0L Rn Rd imm12
13027ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      A5-32   3 | 32  cond 0110 UB0L Rn Rd imm5  sh2 0 Rm
13028ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   */
13029ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* case coding:
13030ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             1   at-ea               (access at ea)
13031ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             2   at-ea-then-upd      (access at ea, then Rn = ea)
13032ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             3   at-Rn-then-upd      (access at Rn, then Rn = ea)
13033ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ea coding
13034ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             16  Rn +/- imm12
13035ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             32  Rn +/- Rm sh2 imm5
13036ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   */
13037ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Quickly skip over all of this for hopefully most instructions */
13038ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if ((INSN(27,24) & BITS4(1,1,0,0)) != BITS4(0,1,0,0))
13039ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      goto after_load_store_ubyte_or_word;
13040ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13041ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   summary = 0;
13042ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13043ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /**/ if (INSN(27,24) == BITS4(0,1,0,1) && INSN(21,21) == 0) {
13044ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      summary = 1 | 16;
13045ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
13046ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   else if (INSN(27,24) == BITS4(0,1,1,1) && INSN(21,21) == 0
13047ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                          && INSN(4,4) == 0) {
13048ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      summary = 1 | 32;
13049ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
13050ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   else if (INSN(27,24) == BITS4(0,1,0,1) && INSN(21,21) == 1) {
13051ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      summary = 2 | 16;
13052ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
13053ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   else if (INSN(27,24) == BITS4(0,1,1,1) && INSN(21,21) == 1
13054ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                          && INSN(4,4) == 0) {
13055ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      summary = 2 | 32;
13056ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
13057ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   else if (INSN(27,24) == BITS4(0,1,0,0) && INSN(21,21) == 0) {
13058ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      summary = 3 | 16;
13059ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
13060ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   else if (INSN(27,24) == BITS4(0,1,1,0) && INSN(21,21) == 0
13061ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                          && INSN(4,4) == 0) {
13062ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      summary = 3 | 32;
13063ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
13064ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   else goto after_load_store_ubyte_or_word;
13065ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13066ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   { UInt rN = (insn >> 16) & 0xF; /* 19:16 */
13067ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     UInt rD = (insn >> 12) & 0xF; /* 15:12 */
13068ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     UInt rM = (insn >> 0)  & 0xF; /*  3:0  */
13069ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     UInt bU = (insn >> 23) & 1;      /* 23 */
13070ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     UInt bB = (insn >> 22) & 1;      /* 22 */
13071ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     UInt bL = (insn >> 20) & 1;      /* 20 */
13072ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     UInt imm12 = (insn >> 0) & 0xFFF; /* 11:0 */
13073ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     UInt imm5  = (insn >> 7) & 0x1F;  /* 11:7 */
13074ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     UInt sh2   = (insn >> 5) & 3;     /* 6:5 */
13075ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13076ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     /* Skip some invalid cases, which would lead to two competing
13077ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        updates to the same register, or which are otherwise
13078ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        disallowed by the spec. */
13079ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     switch (summary) {
13080ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case 1 | 16:
13081ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           break;
13082ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case 1 | 32:
13083ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           if (rM == 15) goto after_load_store_ubyte_or_word;
13084ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           break;
13085ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case 2 | 16: case 3 | 16:
13086ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           if (rN == 15) goto after_load_store_ubyte_or_word;
13087ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           if (bL == 1 && rN == rD) goto after_load_store_ubyte_or_word;
13088ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           break;
13089ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case 2 | 32: case 3 | 32:
13090ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           if (rM == 15) goto after_load_store_ubyte_or_word;
13091ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           if (rN == 15) goto after_load_store_ubyte_or_word;
13092ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           if (rN == rM) goto after_load_store_ubyte_or_word;
13093ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           if (bL == 1 && rN == rD) goto after_load_store_ubyte_or_word;
13094ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           break;
13095ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        default:
13096ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           vassert(0);
13097ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     }
13098ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13099ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     /* Now, we can't do a conditional load or store, since that very
13100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        likely will generate an exception.  So we have to take a side
13101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        exit at this point if the condition is false. */
13102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     if (condT != IRTemp_INVALID) {
13103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        mk_skip_over_A32_if_cond_is_false( condT );
13104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        condT = IRTemp_INVALID;
13105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     }
13106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     /* Ok, now we're unconditional.  Do the load or store. */
13107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     /* compute the effective address.  Bind it to a tmp since we
13109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        may need to use it twice. */
13110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     IRExpr* eaE = NULL;
13111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     switch (summary & 0xF0) {
13112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case 16:
13113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           eaE = mk_EA_reg_plusminus_imm12( rN, bU, imm12, dis_buf );
13114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           break;
13115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case 32:
13116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           eaE = mk_EA_reg_plusminus_shifted_reg( rN, bU, rM, sh2, imm5,
13117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                                  dis_buf );
13118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           break;
13119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     }
13120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     vassert(eaE);
13121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     IRTemp eaT = newTemp(Ity_I32);
13122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     assign(eaT, eaE);
13123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     /* get the old Rn value */
13125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     IRTemp rnT = newTemp(Ity_I32);
13126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     assign(rnT, getIRegA(rN));
13127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     /* decide on the transfer address */
13129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     IRTemp taT = IRTemp_INVALID;
13130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     switch (summary & 0x0F) {
13131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case 1: case 2: taT = eaT; break;
13132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case 3:         taT = rnT; break;
13133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     }
13134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     vassert(taT != IRTemp_INVALID);
13135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     if (bL == 0) {
13137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       /* Store.  If necessary, update the base register before the
13138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          store itself, so that the common idiom of "str rX, [sp,
13139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          #-4]!" (store rX at sp-4, then do new sp = sp-4, a.k.a "push
13140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          rX") doesn't cause Memcheck to complain that the access is
13141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          below the stack pointer.  Also, not updating sp before the
13142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          store confuses Valgrind's dynamic stack-extending logic.  So
13143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          do it before the store.  Hence we need to snarf the store
13144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          data before doing the basereg update. */
13145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* get hold of the data to be stored */
13147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        IRTemp rDt = newTemp(Ity_I32);
13148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        assign(rDt, getIRegA(rD));
13149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* Update Rn if necessary. */
13151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        switch (summary & 0x0F) {
13152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           case 2: case 3:
13153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              putIRegA( rN, mkexpr(eaT), IRTemp_INVALID, Ijk_Boring );
13154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              break;
13155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
13156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* generate the transfer */
13158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (bB == 0) { // word store
13159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           storeLE( mkexpr(taT), mkexpr(rDt) );
13160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        } else { // byte store
13161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           vassert(bB == 1);
13162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           storeLE( mkexpr(taT), unop(Iop_32to8, mkexpr(rDt)) );
13163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
13164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     } else {
13166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* Load */
13167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        vassert(bL == 1);
13168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* generate the transfer */
13170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (bB == 0) { // word load
13171b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov           IRTemp jk = Ijk_Boring;
13172b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov           /* According to the Cortex A8 TRM Sec. 5.2.1, LDR(1) with r13 as the
13173b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               base register and PC as the destination register is a return for
13174b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               purposes of branch prediction.
13175b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov              The ARM ARM Sec. C9.10.1 further specifies that it must use a
13176b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               post-increment by immediate addressing mode to be counted in
13177b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               event 0x0E (Procedure return).*/
13178b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov           if (rN == 13 && summary == (3 | 16) && bB == 0) {
13179b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov              jk = Ijk_Ret;
13180b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov           }
13181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           putIRegA( rD, loadLE(Ity_I32, mkexpr(taT)),
13182b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                     IRTemp_INVALID, jk );
13183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        } else { // byte load
13184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           vassert(bB == 1);
13185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           putIRegA( rD, unop(Iop_8Uto32, loadLE(Ity_I8, mkexpr(taT))),
13186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     IRTemp_INVALID, Ijk_Boring );
13187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
13188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* Update Rn if necessary. */
13190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        switch (summary & 0x0F) {
13191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           case 2: case 3:
13192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              // should be assured by logic above:
13193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              if (bL == 1)
13194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 vassert(rD != rN); /* since we just wrote rD */
13195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              putIRegA( rN, mkexpr(eaT), IRTemp_INVALID, Ijk_Boring );
13196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              break;
13197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
13198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     }
13199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     switch (summary & 0x0F) {
13201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case 1:  DIP("%sr%s%s r%u, %s\n",
13202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     bL == 0 ? "st" : "ld",
13203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     bB == 0 ? "" : "b", nCC(INSN_COND), rD, dis_buf);
13204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 break;
13205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case 2:  DIP("%sr%s%s r%u, %s! (at-EA-then-Rn=EA)\n",
13206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     bL == 0 ? "st" : "ld",
13207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     bB == 0 ? "" : "b", nCC(INSN_COND), rD, dis_buf);
13208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 break;
13209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case 3:  DIP("%sr%s%s r%u, %s! (at-Rn-then-Rn=EA)\n",
13210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     bL == 0 ? "st" : "ld",
13211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     bB == 0 ? "" : "b", nCC(INSN_COND), rD, dis_buf);
13212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 break;
13213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        default: vassert(0);
13214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     }
13215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     /* XXX deal with alignment constraints */
13217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     goto decode_success;
13219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     /* Complications:
13221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        For all loads: if the Amode specifies base register
13223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        writeback, and the same register is specified for Rd and Rn,
13224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        the results are UNPREDICTABLE.
13225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        For all loads and stores: if R15 is written, branch to
13227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        that address afterwards.
13228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        STRB: straightforward
13230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        LDRB: loaded data is zero extended
13231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        STR:  lowest 2 bits of address are ignored
13232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        LDR:  if the lowest 2 bits of the address are nonzero
13233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              then the loaded value is rotated right by 8 * the lowest 2 bits
13234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     */
13235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
13236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  after_load_store_ubyte_or_word:
13238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* --------------------- Load/store (sbyte & hword) -------- */
13240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // LDRH LDRSH STRH LDRSB
13241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /*                 31   27   23   19 15 11   7    3     # highest bit
13242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        28   24   20 16 12    8    4    0
13243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      A5-36   1 | 16  cond 0001 U10L Rn Rd im4h 1SH1 im4l
13244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      A5-38   1 | 32  cond 0001 U00L Rn Rd 0000 1SH1 Rm
13245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      A5-40   2 | 16  cond 0001 U11L Rn Rd im4h 1SH1 im4l
13246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      A5-42   2 | 32  cond 0001 U01L Rn Rd 0000 1SH1 Rm
13247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      A5-44   3 | 16  cond 0000 U10L Rn Rd im4h 1SH1 im4l
13248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      A5-46   3 | 32  cond 0000 U00L Rn Rd 0000 1SH1 Rm
13249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   */
13250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* case coding:
13251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             1   at-ea               (access at ea)
13252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             2   at-ea-then-upd      (access at ea, then Rn = ea)
13253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             3   at-Rn-then-upd      (access at Rn, then Rn = ea)
13254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ea coding
13255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             16  Rn +/- imm8
13256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             32  Rn +/- Rm
13257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   */
13258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Quickly skip over all of this for hopefully most instructions */
13259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if ((INSN(27,24) & BITS4(1,1,1,0)) != BITS4(0,0,0,0))
13260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      goto after_load_store_sbyte_or_hword;
13261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Check the "1SH1" thing. */
13263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if ((INSN(7,4) & BITS4(1,0,0,1)) != BITS4(1,0,0,1))
13264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      goto after_load_store_sbyte_or_hword;
13265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   summary = 0;
13267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /**/ if (INSN(27,24) == BITS4(0,0,0,1) && INSN(22,21) == BITS2(1,0)) {
13269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      summary = 1 | 16;
13270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
13271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   else if (INSN(27,24) == BITS4(0,0,0,1) && INSN(22,21) == BITS2(0,0)) {
13272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      summary = 1 | 32;
13273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
13274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   else if (INSN(27,24) == BITS4(0,0,0,1) && INSN(22,21) == BITS2(1,1)) {
13275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      summary = 2 | 16;
13276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
13277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   else if (INSN(27,24) == BITS4(0,0,0,1) && INSN(22,21) == BITS2(0,1)) {
13278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      summary = 2 | 32;
13279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
13280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   else if (INSN(27,24) == BITS4(0,0,0,0) && INSN(22,21) == BITS2(1,0)) {
13281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      summary = 3 | 16;
13282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
13283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   else if (INSN(27,24) == BITS4(0,0,0,0) && INSN(22,21) == BITS2(0,0)) {
13284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      summary = 3 | 32;
13285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
13286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   else goto after_load_store_sbyte_or_hword;
13287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   { UInt rN   = (insn >> 16) & 0xF; /* 19:16 */
13289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     UInt rD   = (insn >> 12) & 0xF; /* 15:12 */
13290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     UInt rM   = (insn >> 0)  & 0xF; /*  3:0  */
13291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     UInt bU   = (insn >> 23) & 1;   /* 23 U=1 offset+, U=0 offset- */
13292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     UInt bL   = (insn >> 20) & 1;   /* 20 L=1 load, L=0 store */
13293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     UInt bH   = (insn >> 5) & 1;    /* H=1 halfword, H=0 byte */
13294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     UInt bS   = (insn >> 6) & 1;    /* S=1 signed, S=0 unsigned */
13295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     UInt imm8 = ((insn >> 4) & 0xF0) | (insn & 0xF); /* 11:8, 3:0 */
13296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     /* Skip combinations that are either meaningless or already
13298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        handled by main word-or-unsigned-byte load-store
13299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        instructions. */
13300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     if (bS == 0 && bH == 0) /* "unsigned byte" */
13301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        goto after_load_store_sbyte_or_hword;
13302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     if (bS == 1 && bL == 0) /* "signed store" */
13303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        goto after_load_store_sbyte_or_hword;
13304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     /* Require 11:8 == 0 for Rn +/- Rm cases */
13306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     if ((summary & 32) != 0 && (imm8 & 0xF0) != 0)
13307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        goto after_load_store_sbyte_or_hword;
13308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     /* Skip some invalid cases, which would lead to two competing
13310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        updates to the same register, or which are otherwise
13311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        disallowed by the spec. */
13312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     switch (summary) {
13313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case 1 | 16:
13314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           break;
13315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case 1 | 32:
13316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           if (rM == 15) goto after_load_store_sbyte_or_hword;
13317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           break;
13318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case 2 | 16: case 3 | 16:
13319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           if (rN == 15) goto after_load_store_sbyte_or_hword;
13320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           if (bL == 1 && rN == rD) goto after_load_store_sbyte_or_hword;
13321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           break;
13322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case 2 | 32: case 3 | 32:
13323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           if (rM == 15) goto after_load_store_sbyte_or_hword;
13324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           if (rN == 15) goto after_load_store_sbyte_or_hword;
13325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           if (rN == rM) goto after_load_store_sbyte_or_hword;
13326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           if (bL == 1 && rN == rD) goto after_load_store_sbyte_or_hword;
13327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           break;
13328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        default:
13329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           vassert(0);
13330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     }
13331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     /* Now, we can't do a conditional load or store, since that very
13333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        likely will generate an exception.  So we have to take a side
13334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        exit at this point if the condition is false. */
13335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     if (condT != IRTemp_INVALID) {
13336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        mk_skip_over_A32_if_cond_is_false( condT );
13337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        condT = IRTemp_INVALID;
13338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     }
13339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     /* Ok, now we're unconditional.  Do the load or store. */
13340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     /* compute the effective address.  Bind it to a tmp since we
13342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        may need to use it twice. */
13343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     IRExpr* eaE = NULL;
13344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     switch (summary & 0xF0) {
13345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case 16:
13346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           eaE = mk_EA_reg_plusminus_imm8( rN, bU, imm8, dis_buf );
13347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           break;
13348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case 32:
13349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           eaE = mk_EA_reg_plusminus_reg( rN, bU, rM, dis_buf );
13350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           break;
13351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     }
13352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     vassert(eaE);
13353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     IRTemp eaT = newTemp(Ity_I32);
13354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     assign(eaT, eaE);
13355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     /* get the old Rn value */
13357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     IRTemp rnT = newTemp(Ity_I32);
13358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     assign(rnT, getIRegA(rN));
13359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     /* decide on the transfer address */
13361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     IRTemp taT = IRTemp_INVALID;
13362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     switch (summary & 0x0F) {
13363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case 1: case 2: taT = eaT; break;
13364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case 3:         taT = rnT; break;
13365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     }
13366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     vassert(taT != IRTemp_INVALID);
13367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     /* halfword store  H 1  L 0  S 0
13369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        uhalf load      H 1  L 1  S 0
13370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        shalf load      H 1  L 1  S 1
13371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        sbyte load      H 0  L 1  S 1
13372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     */
13373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     HChar* name = NULL;
13374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     /* generate the transfer */
13375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     /**/ if (bH == 1 && bL == 0 && bS == 0) { // halfword store
13376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        storeLE( mkexpr(taT), unop(Iop_32to16, getIRegA(rD)) );
13377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        name = "strh";
13378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     }
13379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     else if (bH == 1 && bL == 1 && bS == 0) { // uhalf load
13380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        putIRegA( rD, unop(Iop_16Uto32, loadLE(Ity_I16, mkexpr(taT))),
13381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  IRTemp_INVALID, Ijk_Boring );
13382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        name = "ldrh";
13383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     }
13384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     else if (bH == 1 && bL == 1 && bS == 1) { // shalf load
13385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        putIRegA( rD, unop(Iop_16Sto32, loadLE(Ity_I16, mkexpr(taT))),
13386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  IRTemp_INVALID, Ijk_Boring );
13387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        name = "ldrsh";
13388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     }
13389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     else if (bH == 0 && bL == 1 && bS == 1) { // sbyte load
13390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        putIRegA( rD, unop(Iop_8Sto32, loadLE(Ity_I8, mkexpr(taT))),
13391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  IRTemp_INVALID, Ijk_Boring );
13392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        name = "ldrsb";
13393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     }
13394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     else
13395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        vassert(0); // should be assured by logic above
13396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     /* Update Rn if necessary. */
13398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     switch (summary & 0x0F) {
13399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case 2: case 3:
13400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           // should be assured by logic above:
13401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           if (bL == 1)
13402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              vassert(rD != rN); /* since we just wrote rD */
13403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           putIRegA( rN, mkexpr(eaT), IRTemp_INVALID, Ijk_Boring );
13404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           break;
13405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     }
13406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     switch (summary & 0x0F) {
13408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case 1:  DIP("%s%s r%u, %s\n", name, nCC(INSN_COND), rD, dis_buf);
13409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 break;
13410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case 2:  DIP("%s%s r%u, %s! (at-EA-then-Rn=EA)\n",
13411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     name, nCC(INSN_COND), rD, dis_buf);
13412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 break;
13413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case 3:  DIP("%s%s r%u, %s! (at-Rn-then-Rn=EA)\n",
13414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     name, nCC(INSN_COND), rD, dis_buf);
13415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 break;
13416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        default: vassert(0);
13417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     }
13418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     /* XXX deal with alignment constraints */
13420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     goto decode_success;
13422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     /* Complications:
13424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        For all loads: if the Amode specifies base register
13426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        writeback, and the same register is specified for Rd and Rn,
13427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        the results are UNPREDICTABLE.
13428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        For all loads and stores: if R15 is written, branch to
13430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        that address afterwards.
13431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        Misaligned halfword stores => Unpredictable
13433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        Misaligned halfword loads  => Unpredictable
13434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     */
13435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
13436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  after_load_store_sbyte_or_hword:
13438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* --------------------- Load/store multiple -------------- */
13440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // LD/STMIA LD/STMIB LD/STMDA LD/STMDB
13441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // Remarkably complex and difficult to get right
13442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // match 27:20 as 100XX0WL
13443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (BITS8(1,0,0,0,0,0,0,0) == (INSN(27,20) & BITS8(1,1,1,0,0,1,0,0))) {
13444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // A5-50 LD/STMIA  cond 1000 10WL Rn RegList
13445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // A5-51 LD/STMIB  cond 1001 10WL Rn RegList
13446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // A5-53 LD/STMDA  cond 1000 00WL Rn RegList
13447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // A5-53 LD/STMDB  cond 1001 00WL Rn RegList
13448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      //                   28   24   20 16       0
13449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt bINC    = (insn >> 23) & 1;
13451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt bBEFORE = (insn >> 24) & 1;
13452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt bL      = (insn >> 20) & 1;  /* load=1, store=0 */
13454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt bW      = (insn >> 21) & 1;  /* Rn wback=1, no wback=0 */
13455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt rN      = (insn >> 16) & 0xF;
13456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt regList = insn & 0xFFFF;
13457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Skip some invalid cases, which would lead to two competing
13458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         updates to the same register, or which are otherwise
13459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         disallowed by the spec.  Note the test above has required
13460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         that S == 0, since that looks like a kernel-mode only thing.
13461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         Done by forcing the real pattern, viz 100XXSWL to actually be
13462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         100XX0WL. */
13463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (rN == 15) goto after_load_store_multiple;
13464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // reglist can't be empty
13465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (regList == 0) goto after_load_store_multiple;
13466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // if requested to writeback Rn, and this is a load instruction,
13467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // then Rn can't appear in RegList, since we'd have two competing
13468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // new values for Rn.  We do however accept this case for store
13469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // instructions.
13470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (bW == 1 && bL == 1 && ((1 << rN) & regList) > 0)
13471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto after_load_store_multiple;
13472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Now, we can't do a conditional load or store, since that very
13474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         likely will generate an exception.  So we have to take a side
13475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         exit at this point if the condition is false. */
13476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (condT != IRTemp_INVALID) {
13477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         mk_skip_over_A32_if_cond_is_false( condT );
13478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         condT = IRTemp_INVALID;
13479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
13480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Ok, now we're unconditional.  Generate the IR. */
13482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      mk_ldm_stm( True/*arm*/, rN, bINC, bBEFORE, bW, bL, regList );
13483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("%sm%c%c%s r%u%s, {0x%04x}\n",
13485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          bL == 1 ? "ld" : "st", bINC ? 'i' : 'd', bBEFORE ? 'b' : 'a',
13486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          nCC(INSN_COND),
13487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          rN, bW ? "!" : "", regList);
13488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      goto decode_success;
13490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
13491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  after_load_store_multiple:
13493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* --------------------- Control flow --------------------- */
13495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // B, BL (Branch, or Branch-and-Link, to immediate offset)
13496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //
13497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (BITS8(1,0,1,0,0,0,0,0) == (INSN(27,20) & BITS8(1,1,1,0,0,0,0,0))) {
13498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt link   = (insn >> 24) & 1;
13499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt uimm24 = insn & ((1<<24)-1);
13500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Int  simm24 = (Int)uimm24;
13501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt dst    = guest_R15_curr_instr_notENC + 8
13502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    + (((simm24 << 8) >> 8) << 2);
13503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRJumpKind jk = link ? Ijk_Call : Ijk_Boring;
13504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (link) {
13505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putIRegA(14, mkU32(guest_R15_curr_instr_notENC + 4),
13506ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      condT, Ijk_Boring);
13507ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
13508ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (condT == IRTemp_INVALID) {
13509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* unconditional transfer to 'dst'.  See if we can simply
13510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            continue tracing at the destination. */
13511ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (resteerOkFn( callback_opaque, (Addr64)dst )) {
13512ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* yes */
13513ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            dres.whatNext   = Dis_ResteerU;
13514ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            dres.continueAt = (Addr64)dst;
13515ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
13516ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* no; terminate the SB at this point. */
13517663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            llPutIReg(15, mkU32(dst));
13518663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            dres.jk_StopHere = jk;
13519663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            dres.whatNext    = Dis_StopHere;
13520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
13521ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("b%s 0x%x\n", link ? "l" : "", dst);
13522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else {
13523ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* conditional transfer to 'dst' */
13524ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HChar* comment = "";
13525ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13526ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* First see if we can do some speculative chasing into one
13527ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            arm or the other.  Be conservative and only chase if
13528ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            !link, that is, this is a normal conditional branch to a
13529ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            known destination. */
13530ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (!link
13531ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             && resteerCisOk
13532ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             && vex_control.guest_chase_cond
13533ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             && dst < guest_R15_curr_instr_notENC
13534ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             && resteerOkFn( callback_opaque, (Addr64)(Addr32)dst) ) {
13535ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* Speculation: assume this backward branch is taken.  So
13536ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               we need to emit a side-exit to the insn following this
13537ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               one, on the negation of the condition, and continue at
13538ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               the branch target address (dst). */
13539ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            stmt( IRStmt_Exit( unop(Iop_Not1,
13540ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                    unop(Iop_32to1, mkexpr(condT))),
13541ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               Ijk_Boring,
13542663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                               IRConst_U32(guest_R15_curr_instr_notENC+4),
13543663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                               OFFB_R15T ));
13544ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            dres.whatNext   = Dis_ResteerC;
13545ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            dres.continueAt = (Addr64)(Addr32)dst;
13546ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            comment = "(assumed taken)";
13547ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
13548ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         else
13549ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (!link
13550ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             && resteerCisOk
13551ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             && vex_control.guest_chase_cond
13552ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             && dst >= guest_R15_curr_instr_notENC
13553ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             && resteerOkFn( callback_opaque,
13554ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             (Addr64)(Addr32)
13555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                     (guest_R15_curr_instr_notENC+4)) ) {
13556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* Speculation: assume this forward branch is not taken.
13557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               So we need to emit a side-exit to dst (the dest) and
13558ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               continue disassembling at the insn immediately
13559ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               following this one. */
13560ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            stmt( IRStmt_Exit( unop(Iop_32to1, mkexpr(condT)),
13561ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               Ijk_Boring,
13562663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                               IRConst_U32(dst),
13563663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                               OFFB_R15T ));
13564ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            dres.whatNext   = Dis_ResteerC;
13565ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            dres.continueAt = (Addr64)(Addr32)
13566ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                      (guest_R15_curr_instr_notENC+4);
13567ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            comment = "(assumed not taken)";
13568ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
13569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         else {
13570ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* Conservative default translation - end the block at
13571ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               this point. */
13572ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            stmt( IRStmt_Exit( unop(Iop_32to1, mkexpr(condT)),
13573663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                               jk, IRConst_U32(dst), OFFB_R15T ));
13574663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            llPutIReg(15, mkU32(guest_R15_curr_instr_notENC + 4));
13575663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            dres.jk_StopHere = Ijk_Boring;
13576663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            dres.whatNext    = Dis_StopHere;
13577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
13578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("b%s%s 0x%x %s\n", link ? "l" : "", nCC(INSN_COND),
13579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             dst, comment);
13580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
13581ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      goto decode_success;
13582ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
13583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13584ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // B, BL (Branch, or Branch-and-Link, to a register)
13585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // NB: interworking branch
13586ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (INSN(27,20) == BITS8(0,0,0,1,0,0,1,0)
13587ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && INSN(19,12) == BITS8(1,1,1,1,1,1,1,1)
13588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && (INSN(11,4) == BITS8(1,1,1,1,0,0,1,1)
13589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           || INSN(11,4) == BITS8(1,1,1,1,0,0,0,1))) {
13590b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      IRTemp  dst = newTemp(Ity_I32);
13591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt    link = (INSN(11,4) >> 1) & 1;
13592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt    rM   = INSN(3,0);
13593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // we don't decode the case (link && rM == 15), as that's
13594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // Unpredictable.
13595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (!(link && rM == 15)) {
13596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (condT != IRTemp_INVALID) {
13597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            mk_skip_over_A32_if_cond_is_false( condT );
13598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
13599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         // rM contains an interworking address exactly as we require
13600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         // (with continuation CPSR.T in bit 0), so we can use it
13601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         // as-is, with no masking.
13602b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         assign( dst, getIRegA(rM) );
13603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (link) {
13604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            putIRegA( 14, mkU32(guest_R15_curr_instr_notENC + 4),
13605ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      IRTemp_INVALID/*because AL*/, Ijk_Boring );
13606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
13607663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         llPutIReg(15, mkexpr(dst));
13608663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         dres.jk_StopHere = link ? Ijk_Call
13609663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                                 : (rM == 14 ? Ijk_Ret : Ijk_Boring);
13610663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         dres.whatNext    = Dis_StopHere;
13611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (condT == IRTemp_INVALID) {
13612ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            DIP("b%sx r%u\n", link ? "l" : "", rM);
13613ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
13614ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            DIP("b%sx%s r%u\n", link ? "l" : "", nCC(INSN_COND), rM);
13615ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
13616ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto decode_success;
13617ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
13618ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* else: (link && rM == 15): just fall through */
13619ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
13620ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13621ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* --- NB: ARM interworking branches are in NV space, hence
13622ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      are handled elsewhere by decode_NV_instruction.
13623ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ---
13624ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   */
13625ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13626ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* --------------------- Clz --------------------- */
13627ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // CLZ
13628ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (INSN(27,20) == BITS8(0,0,0,1,0,1,1,0)
13629ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && INSN(19,16) == BITS4(1,1,1,1)
13630ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && INSN(11,4) == BITS8(1,1,1,1,0,0,0,1)) {
13631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt rD = INSN(15,12);
13632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt rM = INSN(3,0);
13633ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp arg = newTemp(Ity_I32);
13634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp res = newTemp(Ity_I32);
13635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign(arg, getIRegA(rM));
13636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign(res, IRExpr_Mux0X(
13637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     unop(Iop_1Uto8,binop(Iop_CmpEQ32, mkexpr(arg),
13638ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                                       mkU32(0))),
13639ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     unop(Iop_Clz32, mkexpr(arg)),
13640ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     mkU32(32)
13641ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ));
13642ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putIRegA(rD, mkexpr(res), condT, Ijk_Boring);
13643ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("clz%s r%u, r%u\n", nCC(INSN_COND), rD, rM);
13644ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      goto decode_success;
13645ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
13646ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13647ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* --------------------- Mul etc --------------------- */
13648ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // MUL
13649ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (BITS8(0,0,0,0,0,0,0,0) == (INSN(27,20) & BITS8(1,1,1,1,1,1,1,0))
13650ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && INSN(15,12) == BITS4(0,0,0,0)
13651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && INSN(7,4) == BITS4(1,0,0,1)) {
13652ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt bitS = (insn >> 20) & 1; /* 20:20 */
13653ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt rD = INSN(19,16);
13654ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt rS = INSN(11,8);
13655ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt rM = INSN(3,0);
13656ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (rD == 15 || rM == 15 || rS == 15) {
13657ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Unpredictable; don't decode; fall through */
13658ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else {
13659ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp argL = newTemp(Ity_I32);
13660ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp argR = newTemp(Ity_I32);
13661ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp res  = newTemp(Ity_I32);
13662ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp oldC = IRTemp_INVALID;
13663ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp oldV = IRTemp_INVALID;
13664ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( argL, getIRegA(rM));
13665ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( argR, getIRegA(rS));
13666ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( res, binop(Iop_Mul32, mkexpr(argL), mkexpr(argR)) );
13667ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (bitS) {
13668ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            oldC = newTemp(Ity_I32);
13669ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            assign(oldC, mk_armg_calculate_flag_c());
13670ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            oldV = newTemp(Ity_I32);
13671ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            assign(oldV, mk_armg_calculate_flag_v());
13672ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
13673ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         // now update guest state
13674ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putIRegA( rD, mkexpr(res), condT, Ijk_Boring );
13675ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (bitS) {
13676ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            IRTemp pair = newTemp(Ity_I32);
13677ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            assign( pair, binop(Iop_Or32,
13678ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                binop(Iop_Shl32, mkexpr(oldC), mkU8(1)),
13679ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                mkexpr(oldV)) );
13680ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            setFlags_D1_ND( ARMG_CC_OP_MUL, res, pair, condT );
13681ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
13682ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("mul%c%s r%u, r%u, r%u\n",
13683ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             bitS ? 's' : ' ', nCC(INSN_COND), rD, rM, rS);
13684ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto decode_success;
13685ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
13686ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* fall through */
13687ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
13688ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
136896d67c5925dfb5eae9a15380403fa2a81e18a91eaBen Cheng   /* --------------------- Integer Divides --------------------- */
136906d67c5925dfb5eae9a15380403fa2a81e18a91eaBen Cheng   // SDIV
136916d67c5925dfb5eae9a15380403fa2a81e18a91eaBen Cheng   if (BITS8(0,1,1,1,0,0,0,1) == INSN(27,20)
136926d67c5925dfb5eae9a15380403fa2a81e18a91eaBen Cheng       && INSN(15,12) == BITS4(1,1,1,1)
136936d67c5925dfb5eae9a15380403fa2a81e18a91eaBen Cheng       && INSN(7,4) == BITS4(0,0,0,1)) {
136946d67c5925dfb5eae9a15380403fa2a81e18a91eaBen Cheng      UInt rD = INSN(19,16);
136956d67c5925dfb5eae9a15380403fa2a81e18a91eaBen Cheng      UInt rM = INSN(11,8);
136966d67c5925dfb5eae9a15380403fa2a81e18a91eaBen Cheng      UInt rN = INSN(3,0);
136976d67c5925dfb5eae9a15380403fa2a81e18a91eaBen Cheng      if (rD == 15 || rM == 15 || rN == 15) {
136986d67c5925dfb5eae9a15380403fa2a81e18a91eaBen Cheng         /* Unpredictable; don't decode; fall through */
136996d67c5925dfb5eae9a15380403fa2a81e18a91eaBen Cheng      } else {
137006d67c5925dfb5eae9a15380403fa2a81e18a91eaBen Cheng         IRTemp res = newTemp(Ity_I32);
137016d67c5925dfb5eae9a15380403fa2a81e18a91eaBen Cheng         IRTemp argL  = newTemp(Ity_I32);
137026d67c5925dfb5eae9a15380403fa2a81e18a91eaBen Cheng         IRTemp argR  = newTemp(Ity_I32);
137036d67c5925dfb5eae9a15380403fa2a81e18a91eaBen Cheng         assign(argL, getIRegA(rN));
137046d67c5925dfb5eae9a15380403fa2a81e18a91eaBen Cheng         assign(argR, getIRegA(rM));
137056d67c5925dfb5eae9a15380403fa2a81e18a91eaBen Cheng         assign(res, binop(Iop_DivS32, mkexpr(argL), mkexpr(argR)));
137066d67c5925dfb5eae9a15380403fa2a81e18a91eaBen Cheng         putIRegA(rD, mkexpr(res), condT, Ijk_Boring);
137076d67c5925dfb5eae9a15380403fa2a81e18a91eaBen Cheng         DIP("sdiv r%u, r%u, r%u\n", rD, rN, rM);
137086d67c5925dfb5eae9a15380403fa2a81e18a91eaBen Cheng         goto decode_success;
137096d67c5925dfb5eae9a15380403fa2a81e18a91eaBen Cheng      }
137106d67c5925dfb5eae9a15380403fa2a81e18a91eaBen Cheng    }
137116d67c5925dfb5eae9a15380403fa2a81e18a91eaBen Cheng
137126d67c5925dfb5eae9a15380403fa2a81e18a91eaBen Cheng   // UDIV
137136d67c5925dfb5eae9a15380403fa2a81e18a91eaBen Cheng   if (BITS8(0,1,1,1,0,0,1,1) == INSN(27,20)
137146d67c5925dfb5eae9a15380403fa2a81e18a91eaBen Cheng       && INSN(15,12) == BITS4(1,1,1,1)
137156d67c5925dfb5eae9a15380403fa2a81e18a91eaBen Cheng       && INSN(7,4) == BITS4(0,0,0,1)) {
137166d67c5925dfb5eae9a15380403fa2a81e18a91eaBen Cheng      UInt rD = INSN(19,16);
137176d67c5925dfb5eae9a15380403fa2a81e18a91eaBen Cheng      UInt rM = INSN(11,8);
137186d67c5925dfb5eae9a15380403fa2a81e18a91eaBen Cheng      UInt rN = INSN(3,0);
137196d67c5925dfb5eae9a15380403fa2a81e18a91eaBen Cheng      if (rD == 15 || rM == 15 || rN == 15) {
137206d67c5925dfb5eae9a15380403fa2a81e18a91eaBen Cheng         /* Unpredictable; don't decode; fall through */
137216d67c5925dfb5eae9a15380403fa2a81e18a91eaBen Cheng      } else {
137226d67c5925dfb5eae9a15380403fa2a81e18a91eaBen Cheng         IRTemp res = newTemp(Ity_I32);
137236d67c5925dfb5eae9a15380403fa2a81e18a91eaBen Cheng         IRTemp argL  = newTemp(Ity_I32);
137246d67c5925dfb5eae9a15380403fa2a81e18a91eaBen Cheng         IRTemp argR  = newTemp(Ity_I32);
137256d67c5925dfb5eae9a15380403fa2a81e18a91eaBen Cheng         assign(argL, getIRegA(rN));
137266d67c5925dfb5eae9a15380403fa2a81e18a91eaBen Cheng         assign(argR, getIRegA(rM));
137276d67c5925dfb5eae9a15380403fa2a81e18a91eaBen Cheng         assign(res, binop(Iop_DivU32, mkexpr(argL), mkexpr(argR)));
137286d67c5925dfb5eae9a15380403fa2a81e18a91eaBen Cheng         putIRegA(rD, mkexpr(res), condT, Ijk_Boring);
137296d67c5925dfb5eae9a15380403fa2a81e18a91eaBen Cheng         DIP("udiv r%u, r%u, r%u\n", rD, rN, rM);
137306d67c5925dfb5eae9a15380403fa2a81e18a91eaBen Cheng         goto decode_success;
137316d67c5925dfb5eae9a15380403fa2a81e18a91eaBen Cheng      }
137326d67c5925dfb5eae9a15380403fa2a81e18a91eaBen Cheng    }
137336d67c5925dfb5eae9a15380403fa2a81e18a91eaBen Cheng
13734ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // MLA, MLS
13735ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (BITS8(0,0,0,0,0,0,1,0) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,0))
13736ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && INSN(7,4) == BITS4(1,0,0,1)) {
13737ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt bitS  = (insn >> 20) & 1; /* 20:20 */
13738ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt isMLS = (insn >> 22) & 1; /* 22:22 */
13739ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt rD = INSN(19,16);
13740ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt rN = INSN(15,12);
13741ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt rS = INSN(11,8);
13742ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt rM = INSN(3,0);
13743ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (bitS == 1 && isMLS == 1) {
13744ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* This isn't allowed (MLS that sets flags).  don't decode;
13745ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            fall through */
13746ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
13747ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      else
13748ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (rD == 15 || rM == 15 || rS == 15 || rN == 15) {
13749ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Unpredictable; don't decode; fall through */
13750ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else {
13751ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp argL = newTemp(Ity_I32);
13752ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp argR = newTemp(Ity_I32);
13753ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp argP = newTemp(Ity_I32);
13754ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp res  = newTemp(Ity_I32);
13755ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp oldC = IRTemp_INVALID;
13756ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp oldV = IRTemp_INVALID;
13757ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( argL, getIRegA(rM));
13758ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( argR, getIRegA(rS));
13759ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( argP, getIRegA(rN));
13760ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( res, binop(isMLS ? Iop_Sub32 : Iop_Add32,
13761ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            mkexpr(argP),
13762ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            binop(Iop_Mul32, mkexpr(argL), mkexpr(argR)) ));
13763ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (bitS) {
13764ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vassert(!isMLS); // guaranteed above
13765ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            oldC = newTemp(Ity_I32);
13766ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            assign(oldC, mk_armg_calculate_flag_c());
13767ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            oldV = newTemp(Ity_I32);
13768ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            assign(oldV, mk_armg_calculate_flag_v());
13769ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
13770ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         // now update guest state
13771ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putIRegA( rD, mkexpr(res), condT, Ijk_Boring );
13772ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (bitS) {
13773ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            IRTemp pair = newTemp(Ity_I32);
13774ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            assign( pair, binop(Iop_Or32,
13775ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                binop(Iop_Shl32, mkexpr(oldC), mkU8(1)),
13776ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                mkexpr(oldV)) );
13777ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            setFlags_D1_ND( ARMG_CC_OP_MUL, res, pair, condT );
13778ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
13779ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("ml%c%c%s r%u, r%u, r%u, r%u\n",
13780ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             isMLS ? 's' : 'a', bitS ? 's' : ' ',
13781ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             nCC(INSN_COND), rD, rM, rS, rN);
13782ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto decode_success;
13783ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
13784ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* fall through */
13785ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
13786ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13787ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // SMULL, UMULL
13788ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (BITS8(0,0,0,0,1,0,0,0) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,0))
13789ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && INSN(7,4) == BITS4(1,0,0,1)) {
13790ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt bitS = (insn >> 20) & 1; /* 20:20 */
13791ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt rDhi = INSN(19,16);
13792ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt rDlo = INSN(15,12);
13793ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt rS   = INSN(11,8);
13794ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt rM   = INSN(3,0);
13795ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt isS  = (INSN(27,20) >> 2) & 1; /* 22:22 */
13796ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (rDhi == 15 || rDlo == 15 || rM == 15 || rS == 15 || rDhi == rDlo)  {
13797ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Unpredictable; don't decode; fall through */
13798ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else {
13799ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp argL  = newTemp(Ity_I32);
13800ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp argR  = newTemp(Ity_I32);
13801ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp res   = newTemp(Ity_I64);
13802ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp resHi = newTemp(Ity_I32);
13803ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp resLo = newTemp(Ity_I32);
13804ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp oldC  = IRTemp_INVALID;
13805ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp oldV  = IRTemp_INVALID;
13806ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IROp   mulOp = isS ? Iop_MullS32 : Iop_MullU32;
13807ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( argL, getIRegA(rM));
13808ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( argR, getIRegA(rS));
13809ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( res, binop(mulOp, mkexpr(argL), mkexpr(argR)) );
13810ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( resHi, unop(Iop_64HIto32, mkexpr(res)) );
13811ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( resLo, unop(Iop_64to32, mkexpr(res)) );
13812ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (bitS) {
13813ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            oldC = newTemp(Ity_I32);
13814ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            assign(oldC, mk_armg_calculate_flag_c());
13815ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            oldV = newTemp(Ity_I32);
13816ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            assign(oldV, mk_armg_calculate_flag_v());
13817ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
13818ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         // now update guest state
13819ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putIRegA( rDhi, mkexpr(resHi), condT, Ijk_Boring );
13820ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putIRegA( rDlo, mkexpr(resLo), condT, Ijk_Boring );
13821ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (bitS) {
13822ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            IRTemp pair = newTemp(Ity_I32);
13823ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            assign( pair, binop(Iop_Or32,
13824ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                binop(Iop_Shl32, mkexpr(oldC), mkU8(1)),
13825ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                mkexpr(oldV)) );
13826ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            setFlags_D1_D2_ND( ARMG_CC_OP_MULL, resLo, resHi, pair, condT );
13827ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
13828ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("%cmull%c%s r%u, r%u, r%u, r%u\n",
13829ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             isS ? 's' : 'u', bitS ? 's' : ' ',
13830ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             nCC(INSN_COND), rDlo, rDhi, rM, rS);
13831ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto decode_success;
13832ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
13833ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* fall through */
13834ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
13835ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13836ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // SMLAL, UMLAL
13837ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (BITS8(0,0,0,0,1,0,1,0) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,0))
13838ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && INSN(7,4) == BITS4(1,0,0,1)) {
13839ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt bitS = (insn >> 20) & 1; /* 20:20 */
13840ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt rDhi = INSN(19,16);
13841ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt rDlo = INSN(15,12);
13842ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt rS   = INSN(11,8);
13843ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt rM   = INSN(3,0);
13844ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt isS  = (INSN(27,20) >> 2) & 1; /* 22:22 */
13845ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (rDhi == 15 || rDlo == 15 || rM == 15 || rS == 15 || rDhi == rDlo)  {
13846ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Unpredictable; don't decode; fall through */
13847ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else {
13848ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp argL  = newTemp(Ity_I32);
13849ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp argR  = newTemp(Ity_I32);
13850ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp old   = newTemp(Ity_I64);
13851ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp res   = newTemp(Ity_I64);
13852ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp resHi = newTemp(Ity_I32);
13853ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp resLo = newTemp(Ity_I32);
13854ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp oldC  = IRTemp_INVALID;
13855ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp oldV  = IRTemp_INVALID;
13856ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IROp   mulOp = isS ? Iop_MullS32 : Iop_MullU32;
13857ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( argL, getIRegA(rM));
13858ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( argR, getIRegA(rS));
13859ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( old, binop(Iop_32HLto64, getIRegA(rDhi), getIRegA(rDlo)) );
13860ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( res, binop(Iop_Add64,
13861ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            mkexpr(old),
13862ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            binop(mulOp, mkexpr(argL), mkexpr(argR))) );
13863ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( resHi, unop(Iop_64HIto32, mkexpr(res)) );
13864ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( resLo, unop(Iop_64to32, mkexpr(res)) );
13865ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (bitS) {
13866ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            oldC = newTemp(Ity_I32);
13867ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            assign(oldC, mk_armg_calculate_flag_c());
13868ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            oldV = newTemp(Ity_I32);
13869ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            assign(oldV, mk_armg_calculate_flag_v());
13870ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
13871ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         // now update guest state
13872ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putIRegA( rDhi, mkexpr(resHi), condT, Ijk_Boring );
13873ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putIRegA( rDlo, mkexpr(resLo), condT, Ijk_Boring );
13874ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (bitS) {
13875ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            IRTemp pair = newTemp(Ity_I32);
13876ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            assign( pair, binop(Iop_Or32,
13877ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                binop(Iop_Shl32, mkexpr(oldC), mkU8(1)),
13878ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                mkexpr(oldV)) );
13879ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            setFlags_D1_D2_ND( ARMG_CC_OP_MULL, resLo, resHi, pair, condT );
13880ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
13881ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("%cmlal%c%s r%u, r%u, r%u, r%u\n",
13882ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             isS ? 's' : 'u', bitS ? 's' : ' ', nCC(INSN_COND),
13883ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             rDlo, rDhi, rM, rS);
13884ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto decode_success;
13885ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
13886ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* fall through */
13887ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
13888ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13889ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* --------------------- Msr etc --------------------- */
13890ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13891ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // MSR apsr, #imm
13892ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (INSN(27,20) == BITS8(0,0,1,1,0,0,1,0)
13893ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && INSN(17,12) == BITS6(0,0,1,1,1,1)) {
13894ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt write_ge    = INSN(18,18);
13895ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt write_nzcvq = INSN(19,19);
13896ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (write_nzcvq || write_ge) {
13897ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         UInt   imm = (INSN(11,0) >> 0) & 0xFF;
13898ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         UInt   rot = 2 * ((INSN(11,0) >> 8) & 0xF);
13899ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp immT = newTemp(Ity_I32);
13900ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(rot <= 30);
13901ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         imm = ROR32(imm, rot);
13902ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign(immT, mkU32(imm));
13903ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         desynthesise_APSR( write_nzcvq, write_ge, immT, condT );
13904ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("msr%s cpsr%s%sf, #0x%08x\n", nCC(INSN_COND),
13905ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             write_nzcvq ? "f" : "", write_ge ? "g" : "", imm);
13906ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto decode_success;
13907ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
13908ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* fall through */
13909ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
13910ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13911ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // MSR apsr, reg
13912ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (INSN(27,20) == BITS8(0,0,0,1,0,0,1,0)
13913ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && INSN(17,12) == BITS6(0,0,1,1,1,1)
13914ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && INSN(11,4) == BITS8(0,0,0,0,0,0,0,0)) {
13915ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt rN          = INSN(3,0);
13916ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt write_ge    = INSN(18,18);
13917ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt write_nzcvq = INSN(19,19);
13918ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (rN != 15 && (write_nzcvq || write_ge)) {
13919ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp rNt = newTemp(Ity_I32);
13920ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign(rNt, getIRegA(rN));
13921ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         desynthesise_APSR( write_nzcvq, write_ge, rNt, condT );
13922ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("msr%s cpsr_%s%s, r%u\n", nCC(INSN_COND),
13923ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             write_nzcvq ? "f" : "", write_ge ? "g" : "", rN);
13924ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto decode_success;
13925ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
13926ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* fall through */
13927ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
13928ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13929ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // MRS rD, cpsr
13930ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if ((insn & 0x0FFF0FFF) == 0x010F0000) {
13931ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt rD   = INSN(15,12);
13932ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (rD != 15) {
13933ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp apsr = synthesise_APSR();
13934ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putIRegA( rD, mkexpr(apsr), condT, Ijk_Boring );
13935ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("mrs%s r%u, cpsr\n", nCC(INSN_COND), rD);
13936ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto decode_success;
13937ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
13938ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* fall through */
13939ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
13940ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13941ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* --------------------- Svc --------------------- */
13942ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (BITS8(1,1,1,1,0,0,0,0) == (INSN(27,20) & BITS8(1,1,1,1,0,0,0,0))) {
13943ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt imm24 = (insn >> 0) & 0xFFFFFF;
13944ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (imm24 == 0) {
13945ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* A syscall.  We can't do this conditionally, hence: */
13946ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (condT != IRTemp_INVALID) {
13947ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            mk_skip_over_A32_if_cond_is_false( condT );
13948ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
13949ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         // AL after here
13950663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         llPutIReg(15, mkU32( guest_R15_curr_instr_notENC + 4 ));
13951663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         dres.jk_StopHere = Ijk_Sys_syscall;
13952663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         dres.whatNext    = Dis_StopHere;
13953ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("svc%s #0x%08x\n", nCC(INSN_COND), imm24);
13954ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto decode_success;
13955ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
13956ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* fall through */
13957ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
13958ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13959ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* ------------------------ swp ------------------------ */
13960ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13961ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // SWP, SWPB
13962ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (BITS8(0,0,0,1,0,0,0,0) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,1))
13963ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && BITS4(0,0,0,0) == INSN(11,8)
13964ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && BITS4(1,0,0,1) == INSN(7,4)) {
13965ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt   rN   = INSN(19,16);
13966ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt   rD   = INSN(15,12);
13967ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt   rM   = INSN(3,0);
13968ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp tRn  = newTemp(Ity_I32);
13969ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp tNew = newTemp(Ity_I32);
13970ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp tOld = IRTemp_INVALID;
13971ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp tSC1 = newTemp(Ity_I1);
13972ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt   isB  = (insn >> 22) & 1;
13973ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13974ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (rD == 15 || rN == 15 || rM == 15 || rN == rM || rN == rD) {
13975ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* undecodable; fall through */
13976ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else {
13977ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* make unconditional */
13978ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (condT != IRTemp_INVALID) {
13979ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            mk_skip_over_A32_if_cond_is_false( condT );
13980ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            condT = IRTemp_INVALID;
13981ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
13982ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Ok, now we're unconditional.  Generate a LL-SC loop. */
13983ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign(tRn, getIRegA(rN));
13984ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign(tNew, getIRegA(rM));
13985ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (isB) {
13986ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* swpb */
13987ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            tOld = newTemp(Ity_I8);
13988ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            stmt( IRStmt_LLSC(Iend_LE, tOld, mkexpr(tRn),
13989ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              NULL/*=>isLL*/) );
13990ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            stmt( IRStmt_LLSC(Iend_LE, tSC1, mkexpr(tRn),
13991ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              unop(Iop_32to8, mkexpr(tNew))) );
13992ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
13993ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* swp */
13994ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            tOld = newTemp(Ity_I32);
13995ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            stmt( IRStmt_LLSC(Iend_LE, tOld, mkexpr(tRn),
13996ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              NULL/*=>isLL*/) );
13997ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            stmt( IRStmt_LLSC(Iend_LE, tSC1, mkexpr(tRn),
13998ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              mkexpr(tNew)) );
13999ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
14000ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         stmt( IRStmt_Exit(unop(Iop_Not1, mkexpr(tSC1)),
14001ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           /*Ijk_NoRedir*/Ijk_Boring,
14002663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                           IRConst_U32(guest_R15_curr_instr_notENC),
14003663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                           OFFB_R15T ));
14004ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putIRegA(rD, isB ? unop(Iop_8Uto32, mkexpr(tOld)) : mkexpr(tOld),
14005ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      IRTemp_INVALID, Ijk_Boring);
14006ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("swp%s%s r%u, r%u, [r%u]\n",
14007ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             isB ? "b" : "", nCC(INSN_COND), rD, rM, rN);
14008ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto decode_success;
14009ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
14010ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* fall through */
14011ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
14012ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14013ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* ----------------------------------------------------------- */
14014ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* -- ARMv6 instructions                                    -- */
14015ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* ----------------------------------------------------------- */
14016ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14017b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   /* ------------------- {ldr,str}ex{,b,h,d} ------------------- */
14018b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
14019b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   // LDREXD, LDREX, LDREXH, LDREXB
14020b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   if (0x01900F9F == (insn & 0x0F900FFF)) {
14021b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      UInt   rT    = INSN(15,12);
14022b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      UInt   rN    = INSN(19,16);
14023b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      IRType ty    = Ity_INVALID;
14024b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      IROp   widen = Iop_INVALID;
14025b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      HChar* nm    = NULL;
14026b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      Bool   valid = True;
14027b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      switch (INSN(22,21)) {
14028b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         case 0: nm = "";  ty = Ity_I32; break;
14029b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         case 1: nm = "d"; ty = Ity_I64; break;
14030b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         case 2: nm = "b"; ty = Ity_I8;  widen = Iop_8Uto32; break;
14031b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         case 3: nm = "h"; ty = Ity_I16; widen = Iop_16Uto32; break;
14032b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         default: vassert(0);
14033b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      }
14034b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      if (ty == Ity_I32 || ty == Ity_I16 || ty == Ity_I8) {
14035b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         if (rT == 15 || rN == 15)
14036b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            valid = False;
14037ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else {
14038b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         vassert(ty == Ity_I64);
14039b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         if ((rT & 1) == 1 || rT == 14 || rN == 15)
14040b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            valid = False;
14041b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      }
14042b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      if (valid) {
14043ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp res;
14044ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* make unconditional */
14045ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (condT != IRTemp_INVALID) {
14046b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov           mk_skip_over_A32_if_cond_is_false( condT );
14047b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov           condT = IRTemp_INVALID;
14048ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
14049ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Ok, now we're unconditional.  Do the load. */
14050b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         res = newTemp(ty);
14051b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         // FIXME: assumes little-endian guest
14052ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         stmt( IRStmt_LLSC(Iend_LE, res, getIRegA(rN),
14053ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           NULL/*this is a load*/) );
14054b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         if (ty == Ity_I64) {
14055b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            // FIXME: assumes little-endian guest
14056b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            putIRegA(rT+0, unop(Iop_64to32, mkexpr(res)),
14057b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                           IRTemp_INVALID, Ijk_Boring);
14058b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            putIRegA(rT+1, unop(Iop_64HIto32, mkexpr(res)),
14059b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                           IRTemp_INVALID, Ijk_Boring);
14060b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            DIP("ldrex%s%s r%u, r%u, [r%u]\n",
14061b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                nm, nCC(INSN_COND), rT+0, rT+1, rN);
14062b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         } else {
14063b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            putIRegA(rT, widen == Iop_INVALID
14064b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                            ? mkexpr(res) : unop(widen, mkexpr(res)),
14065b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                     IRTemp_INVALID, Ijk_Boring);
14066b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            DIP("ldrex%s%s r%u, [r%u]\n", nm, nCC(INSN_COND), rT, rN);
14067b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         }
14068ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto decode_success;
14069ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
14070b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      /* undecodable; fall through */
14071ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
14072ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14073b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   // STREXD, STREX, STREXH, STREXB
14074b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   if (0x01800F90 == (insn & 0x0F900FF0)) {
14075b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      UInt   rT     = INSN(3,0);
14076b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      UInt   rN     = INSN(19,16);
14077b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      UInt   rD     = INSN(15,12);
14078b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      IRType ty     = Ity_INVALID;
14079b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      IROp   narrow = Iop_INVALID;
14080b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      HChar* nm     = NULL;
14081b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      Bool   valid  = True;
14082b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      switch (INSN(22,21)) {
14083b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         case 0: nm = "";  ty = Ity_I32; break;
14084b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         case 1: nm = "d"; ty = Ity_I64; break;
14085b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         case 2: nm = "b"; ty = Ity_I8;  narrow = Iop_32to8; break;
14086b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         case 3: nm = "h"; ty = Ity_I16; narrow = Iop_32to16; break;
14087b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         default: vassert(0);
14088b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      }
14089b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      if (ty == Ity_I32 || ty == Ity_I16 || ty == Ity_I8) {
14090b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         if (rD == 15 || rN == 15 || rT == 15
14091b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov             || rD == rN || rD == rT)
14092b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            valid = False;
14093ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else {
14094b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         vassert(ty == Ity_I64);
14095b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         if (rD == 15 || (rT & 1) == 1 || rT == 14 || rN == 15
14096b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov             || rD == rN || rD == rT || rD == rT+1)
14097b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            valid = False;
14098b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      }
14099b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      if (valid) {
14100b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         IRTemp resSC1, resSC32, data;
14101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* make unconditional */
14102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (condT != IRTemp_INVALID) {
14103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            mk_skip_over_A32_if_cond_is_false( condT );
14104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            condT = IRTemp_INVALID;
14105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
14106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Ok, now we're unconditional.  Do the store. */
14107b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         data = newTemp(ty);
14108b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         assign(data,
14109b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                ty == Ity_I64
14110b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                   // FIXME: assumes little-endian guest
14111b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                   ? binop(Iop_32HLto64, getIRegA(rT+1), getIRegA(rT+0))
14112b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                   : narrow == Iop_INVALID
14113b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                      ? getIRegA(rT)
14114b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                      : unop(narrow, getIRegA(rT)));
14115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         resSC1 = newTemp(Ity_I1);
14116b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         // FIXME: assumes little-endian guest
14117b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         stmt( IRStmt_LLSC(Iend_LE, resSC1, getIRegA(rN), mkexpr(data)) );
14118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Set rD to 1 on failure, 0 on success.  Currently we have
14120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            resSC1 == 0 on failure, 1 on success. */
14121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         resSC32 = newTemp(Ity_I32);
14122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign(resSC32,
14123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                unop(Iop_1Uto32, unop(Iop_Not1, mkexpr(resSC1))));
14124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putIRegA(rD, mkexpr(resSC32),
14126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      IRTemp_INVALID, Ijk_Boring);
14127b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         if (ty == Ity_I64) {
14128b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            DIP("strex%s%s r%u, r%u, r%u, [r%u]\n",
14129b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                nm, nCC(INSN_COND), rD, rT, rT+1, rN);
14130b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         } else {
14131b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            DIP("strex%s%s r%u, r%u, [r%u]\n",
14132b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                nm, nCC(INSN_COND), rD, rT, rN);
14133b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         }
14134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto decode_success;
14135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
14136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* fall through */
14137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
14138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* --------------------- movw, movt --------------------- */
14140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (0x03000000 == (insn & 0x0FF00000)
14141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       || 0x03400000 == (insn & 0x0FF00000)) /* pray for CSE */ {
14142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt rD    = INSN(15,12);
14143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt imm16 = (insn & 0xFFF) | ((insn >> 4) & 0x0000F000);
14144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt isT   = (insn >> 22) & 1;
14145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (rD == 15) {
14146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* forget it */
14147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else {
14148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (isT) {
14149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            putIRegA(rD,
14150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     binop(Iop_Or32,
14151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           binop(Iop_And32, getIRegA(rD), mkU32(0xFFFF)),
14152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           mkU32(imm16 << 16)),
14153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     condT, Ijk_Boring);
14154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            DIP("movt%s r%u, #0x%04x\n", nCC(INSN_COND), rD, imm16);
14155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto decode_success;
14156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
14157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            putIRegA(rD, mkU32(imm16), condT, Ijk_Boring);
14158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            DIP("movw%s r%u, #0x%04x\n", nCC(INSN_COND), rD, imm16);
14159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto decode_success;
14160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
14161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
14162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* fall through */
14163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
14164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* ----------- uxtb, sxtb, uxth, sxth, uxtb16, sxtb16 ----------- */
14166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* FIXME: this is an exact duplicate of the Thumb version.  They
14167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      should be commoned up. */
14168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (BITS8(0,1,1,0,1, 0,0,0) == (INSN(27,20) & BITS8(1,1,1,1,1,0,0,0))
14169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && BITS4(1,1,1,1) == INSN(19,16)
14170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && BITS4(0,1,1,1) == INSN(7,4)
14171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && BITS4(0,0, 0,0) == (INSN(11,8) & BITS4(0,0,1,1))) {
14172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt subopc = INSN(27,20) & BITS8(0,0,0,0,0, 1,1,1);
14173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (subopc != BITS4(0,0,0,1) && subopc != BITS4(0,1,0,1)) {
14174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         Int    rot  = (INSN(11,8) >> 2) & 3;
14175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         UInt   rM   = INSN(3,0);
14176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         UInt   rD   = INSN(15,12);
14177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp srcT = newTemp(Ity_I32);
14178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp rotT = newTemp(Ity_I32);
14179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp dstT = newTemp(Ity_I32);
14180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HChar* nm   = "???";
14181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign(srcT, getIRegA(rM));
14182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign(rotT, genROR32(srcT, 8 * rot)); /* 0, 8, 16 or 24 only */
14183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         switch (subopc) {
14184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case BITS4(0,1,1,0): // UXTB
14185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               assign(dstT, unop(Iop_8Uto32, unop(Iop_32to8, mkexpr(rotT))));
14186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               nm = "uxtb";
14187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
14188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case BITS4(0,0,1,0): // SXTB
14189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               assign(dstT, unop(Iop_8Sto32, unop(Iop_32to8, mkexpr(rotT))));
14190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               nm = "sxtb";
14191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
14192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case BITS4(0,1,1,1): // UXTH
14193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               assign(dstT, unop(Iop_16Uto32, unop(Iop_32to16, mkexpr(rotT))));
14194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               nm = "uxth";
14195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
14196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case BITS4(0,0,1,1): // SXTH
14197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               assign(dstT, unop(Iop_16Sto32, unop(Iop_32to16, mkexpr(rotT))));
14198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               nm = "sxth";
14199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
14200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case BITS4(0,1,0,0): // UXTB16
14201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               assign(dstT, binop(Iop_And32, mkexpr(rotT), mkU32(0x00FF00FF)));
14202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               nm = "uxtb16";
14203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
14204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case BITS4(0,0,0,0): { // SXTB16
14205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               IRTemp lo32 = newTemp(Ity_I32);
14206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               IRTemp hi32 = newTemp(Ity_I32);
14207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               assign(lo32, binop(Iop_And32, mkexpr(rotT), mkU32(0xFF)));
14208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               assign(hi32, binop(Iop_Shr32, mkexpr(rotT), mkU8(16)));
14209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               assign(
14210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  dstT,
14211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  binop(Iop_Or32,
14212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        binop(Iop_And32,
14213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              unop(Iop_8Sto32,
14214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                   unop(Iop_32to8, mkexpr(lo32))),
14215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              mkU32(0xFFFF)),
14216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        binop(Iop_Shl32,
14217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              unop(Iop_8Sto32,
14218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                   unop(Iop_32to8, mkexpr(hi32))),
14219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              mkU8(16))
14220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               ));
14221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               nm = "sxtb16";
14222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
14223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
14224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            default:
14225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               vassert(0); // guarded by "if" above
14226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
14227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putIRegA(rD, mkexpr(dstT), condT, Ijk_Boring);
14228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("%s%s r%u, r%u, ROR #%u\n", nm, nCC(INSN_COND), rD, rM, rot);
14229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto decode_success;
14230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
14231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* fall through */
14232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
14233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* ------------------- bfi, bfc ------------------- */
14235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (BITS8(0,1,1,1,1,1,0, 0) == (INSN(27,20) & BITS8(1,1,1,1,1,1,1,0))
14236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && BITS4(0, 0,0,1) == (INSN(7,4) & BITS4(0,1,1,1))) {
14237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt rD  = INSN(15,12);
14238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt rN  = INSN(3,0);
14239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt msb = (insn >> 16) & 0x1F; /* 20:16 */
14240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt lsb = (insn >> 7) & 0x1F;  /* 11:7 */
14241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (rD == 15 || msb < lsb) {
14242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* undecodable; fall through */
14243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else {
14244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp src    = newTemp(Ity_I32);
14245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp olddst = newTemp(Ity_I32);
14246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp newdst = newTemp(Ity_I32);
14247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         UInt   mask = 1 << (msb - lsb);
14248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         mask = (mask - 1) + mask;
14249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(mask != 0); // guaranteed by "msb < lsb" check above
14250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         mask <<= lsb;
14251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign(src, rN == 15 ? mkU32(0) : getIRegA(rN));
14253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign(olddst, getIRegA(rD));
14254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign(newdst,
14255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                binop(Iop_Or32,
14256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   binop(Iop_And32,
14257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         binop(Iop_Shl32, mkexpr(src), mkU8(lsb)),
14258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         mkU32(mask)),
14259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   binop(Iop_And32,
14260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         mkexpr(olddst),
14261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         mkU32(~mask)))
14262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               );
14263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putIRegA(rD, mkexpr(newdst), condT, Ijk_Boring);
14265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (rN == 15) {
14267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            DIP("bfc%s r%u, #%u, #%u\n",
14268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                nCC(INSN_COND), rD, lsb, msb-lsb+1);
14269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
14270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            DIP("bfi%s r%u, r%u, #%u, #%u\n",
14271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                nCC(INSN_COND), rD, rN, lsb, msb-lsb+1);
14272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
14273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto decode_success;
14274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
14275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* fall through */
14276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
14277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* ------------------- {u,s}bfx ------------------- */
14279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (BITS8(0,1,1,1,1,0,1,0) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,0))
14280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && BITS4(0,1,0,1) == (INSN(7,4) & BITS4(0,1,1,1))) {
14281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt rD  = INSN(15,12);
14282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt rN  = INSN(3,0);
14283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt wm1 = (insn >> 16) & 0x1F; /* 20:16 */
14284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt lsb = (insn >> 7) & 0x1F;  /* 11:7 */
14285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt msb = lsb + wm1;
14286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt isU = (insn >> 22) & 1;    /* 22:22 */
14287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (rD == 15 || rN == 15 || msb >= 32) {
14288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* undecodable; fall through */
14289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else {
14290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp src  = newTemp(Ity_I32);
14291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp tmp  = newTemp(Ity_I32);
14292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp res  = newTemp(Ity_I32);
14293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         UInt   mask = ((1 << wm1) - 1) + (1 << wm1);
14294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(msb >= 0 && msb <= 31);
14295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(mask != 0); // guaranteed by msb being in 0 .. 31 inclusive
14296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign(src, getIRegA(rN));
14298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign(tmp, binop(Iop_And32,
14299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           binop(Iop_Shr32, mkexpr(src), mkU8(lsb)),
14300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           mkU32(mask)));
14301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign(res, binop(isU ? Iop_Shr32 : Iop_Sar32,
14302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           binop(Iop_Shl32, mkexpr(tmp), mkU8(31-wm1)),
14303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           mkU8(31-wm1)));
14304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putIRegA(rD, mkexpr(res), condT, Ijk_Boring);
14306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("%s%s r%u, r%u, #%u, #%u\n",
14308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             isU ? "ubfx" : "sbfx",
14309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             nCC(INSN_COND), rD, rN, lsb, wm1 + 1);
14310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto decode_success;
14311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
14312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* fall through */
14313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
14314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* --------------------- Load/store doubleword ------------- */
14316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // LDRD STRD
14317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /*                 31   27   23   19 15 11   7    3     # highest bit
14318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        28   24   20 16 12    8    4    0
14319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      A5-36   1 | 16  cond 0001 U100 Rn Rd im4h 11S1 im4l
14320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      A5-38   1 | 32  cond 0001 U000 Rn Rd 0000 11S1 Rm
14321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      A5-40   2 | 16  cond 0001 U110 Rn Rd im4h 11S1 im4l
14322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      A5-42   2 | 32  cond 0001 U010 Rn Rd 0000 11S1 Rm
14323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      A5-44   3 | 16  cond 0000 U100 Rn Rd im4h 11S1 im4l
14324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      A5-46   3 | 32  cond 0000 U000 Rn Rd 0000 11S1 Rm
14325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   */
14326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* case coding:
14327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             1   at-ea               (access at ea)
14328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             2   at-ea-then-upd      (access at ea, then Rn = ea)
14329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             3   at-Rn-then-upd      (access at Rn, then Rn = ea)
14330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ea coding
14331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             16  Rn +/- imm8
14332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             32  Rn +/- Rm
14333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   */
14334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Quickly skip over all of this for hopefully most instructions */
14335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if ((INSN(27,24) & BITS4(1,1,1,0)) != BITS4(0,0,0,0))
14336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      goto after_load_store_doubleword;
14337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Check the "11S1" thing. */
14339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if ((INSN(7,4) & BITS4(1,1,0,1)) != BITS4(1,1,0,1))
14340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      goto after_load_store_doubleword;
14341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   summary = 0;
14343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /**/ if (INSN(27,24) == BITS4(0,0,0,1) && INSN(22,20) == BITS3(1,0,0)) {
14345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      summary = 1 | 16;
14346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
14347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   else if (INSN(27,24) == BITS4(0,0,0,1) && INSN(22,20) == BITS3(0,0,0)) {
14348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      summary = 1 | 32;
14349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
14350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   else if (INSN(27,24) == BITS4(0,0,0,1) && INSN(22,20) == BITS3(1,1,0)) {
14351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      summary = 2 | 16;
14352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
14353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   else if (INSN(27,24) == BITS4(0,0,0,1) && INSN(22,20) == BITS3(0,1,0)) {
14354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      summary = 2 | 32;
14355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
14356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   else if (INSN(27,24) == BITS4(0,0,0,0) && INSN(22,20) == BITS3(1,0,0)) {
14357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      summary = 3 | 16;
14358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
14359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   else if (INSN(27,24) == BITS4(0,0,0,0) && INSN(22,20) == BITS3(0,0,0)) {
14360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      summary = 3 | 32;
14361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
14362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   else goto after_load_store_doubleword;
14363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   { UInt rN   = (insn >> 16) & 0xF; /* 19:16 */
14365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     UInt rD   = (insn >> 12) & 0xF; /* 15:12 */
14366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     UInt rM   = (insn >> 0)  & 0xF; /*  3:0  */
14367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     UInt bU   = (insn >> 23) & 1;   /* 23 U=1 offset+, U=0 offset- */
14368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     UInt bS   = (insn >> 5) & 1;    /* S=1 store, S=0 load */
14369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     UInt imm8 = ((insn >> 4) & 0xF0) | (insn & 0xF); /* 11:8, 3:0 */
14370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     /* Require rD to be an even numbered register */
14372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     if ((rD & 1) != 0)
14373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        goto after_load_store_doubleword;
14374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     /* Require 11:8 == 0 for Rn +/- Rm cases */
14376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     if ((summary & 32) != 0 && (imm8 & 0xF0) != 0)
14377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        goto after_load_store_doubleword;
14378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     /* Skip some invalid cases, which would lead to two competing
14380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        updates to the same register, or which are otherwise
14381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        disallowed by the spec. */
14382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     switch (summary) {
14383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case 1 | 16:
14384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           break;
14385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case 1 | 32:
14386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           if (rM == 15) goto after_load_store_doubleword;
14387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           break;
14388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case 2 | 16: case 3 | 16:
14389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           if (rN == 15) goto after_load_store_doubleword;
14390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           if (bS == 0 && (rN == rD || rN == rD+1))
14391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              goto after_load_store_doubleword;
14392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           break;
14393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case 2 | 32: case 3 | 32:
14394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           if (rM == 15) goto after_load_store_doubleword;
14395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           if (rN == 15) goto after_load_store_doubleword;
14396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           if (rN == rM) goto after_load_store_doubleword;
14397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           if (bS == 0 && (rN == rD || rN == rD+1))
14398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              goto after_load_store_doubleword;
14399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           break;
14400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        default:
14401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           vassert(0);
14402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     }
14403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     /* Now, we can't do a conditional load or store, since that very
14405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        likely will generate an exception.  So we have to take a side
14406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        exit at this point if the condition is false. */
14407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     if (condT != IRTemp_INVALID) {
14408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        mk_skip_over_A32_if_cond_is_false( condT );
14409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        condT = IRTemp_INVALID;
14410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     }
14411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     /* Ok, now we're unconditional.  Do the load or store. */
14412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     /* compute the effective address.  Bind it to a tmp since we
14414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        may need to use it twice. */
14415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     IRExpr* eaE = NULL;
14416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     switch (summary & 0xF0) {
14417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case 16:
14418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           eaE = mk_EA_reg_plusminus_imm8( rN, bU, imm8, dis_buf );
14419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           break;
14420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case 32:
14421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           eaE = mk_EA_reg_plusminus_reg( rN, bU, rM, dis_buf );
14422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           break;
14423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     }
14424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     vassert(eaE);
14425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     IRTemp eaT = newTemp(Ity_I32);
14426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     assign(eaT, eaE);
14427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     /* get the old Rn value */
14429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     IRTemp rnT = newTemp(Ity_I32);
14430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     assign(rnT, getIRegA(rN));
14431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     /* decide on the transfer address */
14433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     IRTemp taT = IRTemp_INVALID;
14434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     switch (summary & 0x0F) {
14435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case 1: case 2: taT = eaT; break;
14436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case 3:         taT = rnT; break;
14437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     }
14438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     vassert(taT != IRTemp_INVALID);
14439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     /* XXX deal with alignment constraints */
14441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     /* XXX: but the A8 doesn't seem to trap for misaligned loads, so,
14442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        ignore alignment issues for the time being. */
14443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     /* doubleword store  S 1
14445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        doubleword load   S 0
14446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     */
14447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     HChar* name = NULL;
14448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     /* generate the transfers */
14449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     if (bS == 1) { // doubleword store
14450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        storeLE( binop(Iop_Add32, mkexpr(taT), mkU32(0)), getIRegA(rD+0) );
14451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        storeLE( binop(Iop_Add32, mkexpr(taT), mkU32(4)), getIRegA(rD+1) );
14452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        name = "strd";
14453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     } else { // doubleword load
14454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        putIRegA( rD+0,
14455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  loadLE(Ity_I32, binop(Iop_Add32, mkexpr(taT), mkU32(0))),
14456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  IRTemp_INVALID, Ijk_Boring );
14457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        putIRegA( rD+1,
14458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  loadLE(Ity_I32, binop(Iop_Add32, mkexpr(taT), mkU32(4))),
14459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  IRTemp_INVALID, Ijk_Boring );
14460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        name = "ldrd";
14461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     }
14462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     /* Update Rn if necessary. */
14464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     switch (summary & 0x0F) {
14465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case 2: case 3:
14466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           // should be assured by logic above:
14467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           if (bS == 0) {
14468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              vassert(rD+0 != rN); /* since we just wrote rD+0 */
14469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              vassert(rD+1 != rN); /* since we just wrote rD+1 */
14470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           }
14471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           putIRegA( rN, mkexpr(eaT), IRTemp_INVALID, Ijk_Boring );
14472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           break;
14473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     }
14474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     switch (summary & 0x0F) {
14476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case 1:  DIP("%s%s r%u, %s\n", name, nCC(INSN_COND), rD, dis_buf);
14477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 break;
14478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case 2:  DIP("%s%s r%u, %s! (at-EA-then-Rn=EA)\n",
14479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     name, nCC(INSN_COND), rD, dis_buf);
14480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 break;
14481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        case 3:  DIP("%s%s r%u, %s! (at-Rn-then-Rn=EA)\n",
14482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     name, nCC(INSN_COND), rD, dis_buf);
14483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 break;
14484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        default: vassert(0);
14485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     }
14486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     goto decode_success;
14488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
14489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  after_load_store_doubleword:
14491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* ------------------- {s,u}xtab ------------- */
14493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (BITS8(0,1,1,0,1,0,1,0) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,1))
14494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && BITS4(0,0,0,0) == (INSN(11,8) & BITS4(0,0,1,1))
14495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && BITS4(0,1,1,1) == INSN(7,4)) {
14496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt rN  = INSN(19,16);
14497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt rD  = INSN(15,12);
14498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt rM  = INSN(3,0);
14499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt rot = (insn >> 10) & 3;
14500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt isU = INSN(22,22);
14501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (rN == 15/*it's {S,U}XTB*/ || rD == 15 || rM == 15) {
14502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* undecodable; fall through */
14503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else {
14504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp srcL = newTemp(Ity_I32);
14505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp srcR = newTemp(Ity_I32);
14506ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp res  = newTemp(Ity_I32);
14507ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign(srcR, getIRegA(rM));
14508ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign(srcL, getIRegA(rN));
14509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign(res,  binop(Iop_Add32,
14510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            mkexpr(srcL),
14511ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            unop(isU ? Iop_8Uto32 : Iop_8Sto32,
14512ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                 unop(Iop_32to8,
14513ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                      genROR32(srcR, 8 * rot)))));
14514ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putIRegA(rD, mkexpr(res), condT, Ijk_Boring);
14515ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("%cxtab%s r%u, r%u, r%u, ror #%u\n",
14516ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             isU ? 'u' : 's', nCC(INSN_COND), rD, rN, rM, rot);
14517ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto decode_success;
14518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
14519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* fall through */
14520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
14521ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* ------------------- {s,u}xtah ------------- */
14523ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (BITS8(0,1,1,0,1,0,1,1) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,1))
14524ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && BITS4(0,0,0,0) == (INSN(11,8) & BITS4(0,0,1,1))
14525ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && BITS4(0,1,1,1) == INSN(7,4)) {
14526ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt rN  = INSN(19,16);
14527ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt rD  = INSN(15,12);
14528ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt rM  = INSN(3,0);
14529ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt rot = (insn >> 10) & 3;
14530ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt isU = INSN(22,22);
14531ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (rN == 15/*it's {S,U}XTH*/ || rD == 15 || rM == 15) {
14532ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* undecodable; fall through */
14533ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else {
14534ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp srcL = newTemp(Ity_I32);
14535ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp srcR = newTemp(Ity_I32);
14536ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp res  = newTemp(Ity_I32);
14537ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign(srcR, getIRegA(rM));
14538ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign(srcL, getIRegA(rN));
14539ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign(res,  binop(Iop_Add32,
14540ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            mkexpr(srcL),
14541ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            unop(isU ? Iop_16Uto32 : Iop_16Sto32,
14542ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                 unop(Iop_32to16,
14543ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                      genROR32(srcR, 8 * rot)))));
14544ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putIRegA(rD, mkexpr(res), condT, Ijk_Boring);
14545ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14546ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("%cxtah%s r%u, r%u, r%u, ror #%u\n",
14547ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             isU ? 'u' : 's', nCC(INSN_COND), rD, rN, rM, rot);
14548ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto decode_success;
14549ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
14550ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* fall through */
14551ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
14552ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14553ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* ------------------- rev16, rev ------------------ */
14554ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (INSN(27,16) == 0x6BF
14555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && (INSN(11,4) == 0xFB/*rev16*/ || INSN(11,4) == 0xF3/*rev*/)) {
14556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Bool isREV = INSN(11,4) == 0xF3;
14557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt rM    = INSN(3,0);
14558ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt rD    = INSN(15,12);
14559ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (rM != 15 && rD != 15) {
14560ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp rMt = newTemp(Ity_I32);
14561ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign(rMt, getIRegA(rM));
14562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp res = isREV ? gen_REV(rMt) : gen_REV16(rMt);
14563ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putIRegA(rD, mkexpr(res), condT, Ijk_Boring);
14564ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("rev%s%s r%u, r%u\n", isREV ? "" : "16",
14565ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             nCC(INSN_COND), rD, rM);
14566ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto decode_success;
14567ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
14568ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
14569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14570ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* ------------------- rbit ------------------ */
14571ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (INSN(27,16) == 0x6FF && INSN(11,4) == 0xF3) {
14572ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt rD = INSN(15,12);
14573ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt rM = INSN(3,0);
14574ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (rD != 15 && rM != 15) {
14575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp arg = newTemp(Ity_I32);
14576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign(arg, getIRegA(rM));
14577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp res = gen_BITREV(arg);
14578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putIRegA(rD, mkexpr(res), condT, Ijk_Boring);
14579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("rbit r%u, r%u\n", rD, rM);
14580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto decode_success;
14581ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
14582ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
14583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14584ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* ------------------- smmul ------------------ */
14585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (INSN(27,20) == BITS8(0,1,1,1,0,1,0,1)
14586ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && INSN(15,12) == BITS4(1,1,1,1)
14587ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && (INSN(7,4) & BITS4(1,1,0,1)) == BITS4(0,0,0,1)) {
14588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt bitR = INSN(5,5);
14589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt rD = INSN(19,16);
14590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt rM = INSN(11,8);
14591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt rN = INSN(3,0);
14592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (rD != 15 && rM != 15 && rN != 15) {
14593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRExpr* res
14594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         = unop(Iop_64HIto32,
14595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                binop(Iop_Add64,
14596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      binop(Iop_MullS32, getIRegA(rN), getIRegA(rM)),
14597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      mkU64(bitR ? 0x80000000ULL : 0ULL)));
14598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putIRegA(rD, res, condT, Ijk_Boring);
14599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("smmul%s%s r%u, r%u, r%u\n",
14600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             nCC(INSN_COND), bitR ? "r" : "", rD, rN, rM);
14601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto decode_success;
14602ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
14603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
14604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14605bc77a8ffa8558525c970ffbdb710e9a67389c9e2Ben Cheng   /* ------------------- smmla ------------------ */
14606bc77a8ffa8558525c970ffbdb710e9a67389c9e2Ben Cheng   if (INSN(27,20) == BITS8(0,1,1,1,0,1,0,1)
14607bc77a8ffa8558525c970ffbdb710e9a67389c9e2Ben Cheng       && INSN(15,12) != BITS4(1,1,1,1)
14608bc77a8ffa8558525c970ffbdb710e9a67389c9e2Ben Cheng       && (INSN(7,4) & BITS4(1,1,0,1)) == BITS4(0,0,0,1)) {
14609bc77a8ffa8558525c970ffbdb710e9a67389c9e2Ben Cheng      UInt bitR = INSN(5,5);
14610bc77a8ffa8558525c970ffbdb710e9a67389c9e2Ben Cheng      UInt rD = INSN(19,16);
14611bc77a8ffa8558525c970ffbdb710e9a67389c9e2Ben Cheng      UInt rA = INSN(15,12);
14612bc77a8ffa8558525c970ffbdb710e9a67389c9e2Ben Cheng      UInt rM = INSN(11,8);
14613bc77a8ffa8558525c970ffbdb710e9a67389c9e2Ben Cheng      UInt rN = INSN(3,0);
14614bc77a8ffa8558525c970ffbdb710e9a67389c9e2Ben Cheng      if (rD != 15 && rM != 15 && rN != 15) {
14615bc77a8ffa8558525c970ffbdb710e9a67389c9e2Ben Cheng         IRExpr* res
14616bc77a8ffa8558525c970ffbdb710e9a67389c9e2Ben Cheng         = unop(Iop_64HIto32,
14617bc77a8ffa8558525c970ffbdb710e9a67389c9e2Ben Cheng                binop(Iop_Add64,
14618bc77a8ffa8558525c970ffbdb710e9a67389c9e2Ben Cheng                      binop(Iop_Add64,
14619bc77a8ffa8558525c970ffbdb710e9a67389c9e2Ben Cheng                            binop(Iop_32HLto64, getIRegA(rA), mkU32(0)),
14620bc77a8ffa8558525c970ffbdb710e9a67389c9e2Ben Cheng                            binop(Iop_MullS32, getIRegA(rN), getIRegA(rM))),
14621bc77a8ffa8558525c970ffbdb710e9a67389c9e2Ben Cheng                      mkU64(bitR ? 0x80000000ULL : 0ULL)));
14622bc77a8ffa8558525c970ffbdb710e9a67389c9e2Ben Cheng         putIRegA(rD, res, condT, Ijk_Boring);
14623bc77a8ffa8558525c970ffbdb710e9a67389c9e2Ben Cheng         DIP("smmla%s%s r%u, r%u, r%u, r%u\n",
14624bc77a8ffa8558525c970ffbdb710e9a67389c9e2Ben Cheng             nCC(INSN_COND), bitR ? "r" : "", rD, rN, rM, rA);
14625bc77a8ffa8558525c970ffbdb710e9a67389c9e2Ben Cheng         goto decode_success;
14626bc77a8ffa8558525c970ffbdb710e9a67389c9e2Ben Cheng      }
14627bc77a8ffa8558525c970ffbdb710e9a67389c9e2Ben Cheng   }
14628bc77a8ffa8558525c970ffbdb710e9a67389c9e2Ben Cheng
14629ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* ------------------- NOP ------------------ */
14630ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (0x0320F000 == (insn & 0x0FFFFFFF)) {
14631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("nop%s\n", nCC(INSN_COND));
14632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      goto decode_success;
14633ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
14634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* ----------------------------------------------------------- */
14636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* -- ARMv7 instructions                                    -- */
14637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* ----------------------------------------------------------- */
14638ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14639ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* -------------- read CP15 TPIDRURO register ------------- */
14640ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* mrc     p15, 0, r0, c13, c0, 3  up to
14641ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      mrc     p15, 0, r14, c13, c0, 3
14642ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   */
14643ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* I don't know whether this is really v7-only.  But anyway, we
14644ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      have to support it since arm-linux uses TPIDRURO as a thread
14645ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      state register. */
14646ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (0x0E1D0F70 == (insn & 0x0FFF0FFF)) {
14647ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt rD = INSN(15,12);
14648ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (rD <= 14) {
14649ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* skip r15, that's too stupid to handle */
14650ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putIRegA(rD, IRExpr_Get(OFFB_TPIDRURO, Ity_I32),
14651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      condT, Ijk_Boring);
14652ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("mrc%s p15,0, r%u, c13, c0, 3\n", nCC(INSN_COND), rD);
14653ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto decode_success;
14654ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
14655ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* fall through */
14656ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
14657ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14658ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Handle various kinds of barriers.  This is rather indiscriminate
14659ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      in the sense that they are all turned into an IR Fence, which
14660ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      means we don't know which they are, so the back end has to
14661ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      re-emit them all when it comes acrosss an IR Fence.
14662ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   */
14663663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* v6 */ /* mcr 15, 0, rT, c7, c10, 5 */
14664663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (0xEE070FBA == (insn & 0xFFFF0FFF)) {
14665663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      UInt rT = INSN(15,12);
14666663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (rT <= 14) {
14667663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* mcr 15, 0, rT, c7, c10, 5 (v6) equiv to DMB (v7).  Data
14668663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            Memory Barrier -- ensures ordering of memory accesses. */
14669663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         stmt( IRStmt_MBE(Imbe_Fence) );
14670663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         DIP("mcr 15, 0, r%u, c7, c10, 5 (data memory barrier)\n", rT);
14671663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
14672663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
14673663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* fall through */
1467410a4e5850b3ca9d2e88abe08032887cfc8d21515Kenny Root   }
14675663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* other flavours of barrier */
14676663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   switch (insn) {
14677663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case 0xEE070F9A: /* v6 */
14678663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* mcr 15, 0, r0, c7, c10, 4 (v6) equiv to DSB (v7).  Data
14679663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            Synch Barrier -- ensures completion of memory accesses. */
14680663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         stmt( IRStmt_MBE(Imbe_Fence) );
14681663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         DIP("mcr 15, 0, r0, c7, c10, 4 (data synch barrier)\n");
14682663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
14683663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case 0xEE070F95: /* v6 */
14684663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* mcr 15, 0, r0, c7, c5, 4 (v6) equiv to ISB (v7).
14685663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            Instruction Synchronisation Barrier (or Flush Prefetch
14686663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            Buffer) -- a pipe flush, I think.  I suspect we could
14687663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            ignore those, but to be on the safe side emit a fence
14688663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            anyway. */
14689663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         stmt( IRStmt_MBE(Imbe_Fence) );
14690663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         DIP("mcr 15, 0, r0, c7, c5, 4 (insn synch barrier)\n");
14691663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
14692663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      default:
14693663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         break;
14694ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
14695ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14696ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* ----------------------------------------------------------- */
14697ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* -- VFP (CP 10, CP 11) instructions (in ARM mode)         -- */
14698ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* ----------------------------------------------------------- */
14699ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14700ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (INSN_COND != ARMCondNV) {
14701ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Bool ok_vfp = decode_CP10_CP11_instruction (
14702ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       &dres, INSN(27,0), condT, INSN_COND,
14703ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       False/*!isT*/
14704ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    );
14705ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (ok_vfp)
14706ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto decode_success;
14707ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
14708ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14709ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* ----------------------------------------------------------- */
14710ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* -- NEON instructions (in ARM mode)                       -- */
14711ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* ----------------------------------------------------------- */
14712ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14713ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* These are all in NV space, and so are taken care of (far) above,
14714ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      by a call from this function to decode_NV_instruction(). */
14715ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14716ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* ----------------------------------------------------------- */
14717ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* -- v6 media instructions (in ARM mode)                   -- */
14718ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* ----------------------------------------------------------- */
14719ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14720ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   { Bool ok_v6m = decode_V6MEDIA_instruction(
14721ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       &dres, INSN(27,0), condT, INSN_COND,
14722ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       False/*!isT*/
14723ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   );
14724ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     if (ok_v6m)
14725ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        goto decode_success;
14726ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
14727ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14728ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* ----------------------------------------------------------- */
14729ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* -- Undecodable                                           -- */
14730ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* ----------------------------------------------------------- */
14731ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14732ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   goto decode_failure;
14733ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /*NOTREACHED*/
14734ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14735ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  decode_failure:
14736ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* All decode failures end up here. */
14737ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vex_printf("disInstr(arm): unhandled instruction: "
14738ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              "0x%x\n", insn);
14739ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vex_printf("                 cond=%d(0x%x) 27:20=%u(0x%02x) "
14740ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                "4:4=%d "
14741ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                "3:0=%u(0x%x)\n",
14742ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              (Int)INSN_COND, (UInt)INSN_COND,
14743ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              (Int)INSN(27,20), (UInt)INSN(27,20),
14744ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              (Int)INSN(4,4),
14745ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              (Int)INSN(3,0), (UInt)INSN(3,0) );
14746ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14747ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Tell the dispatcher that this insn cannot be decoded, and so has
14748ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      not been executed, and (is currently) the next to be executed.
14749ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      R15 should be up-to-date since it made so at the start of each
14750ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      insn, but nevertheless be paranoid and update it again right
14751ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      now. */
14752ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(0 == (guest_R15_curr_instr_notENC & 3));
14753ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   llPutIReg( 15, mkU32(guest_R15_curr_instr_notENC) );
14754663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   dres.whatNext    = Dis_StopHere;
14755663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   dres.jk_StopHere = Ijk_NoDecode;
14756663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   dres.len         = 0;
14757ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return dres;
14758ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14759ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  decode_success:
14760ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* All decode successes end up here. */
14761ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   DIP("\n");
14762ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14763ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(dres.len == 4 || dres.len == 20);
14764ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14765ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Now then.  Do we have an implicit jump to r15 to deal with? */
14766ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (r15written) {
14767ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* If we get jump to deal with, we assume that there's been no
14768ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         other competing branch stuff previously generated for this
14769ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         insn.  That's reasonable, in the sense that the ARM insn set
14770ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         appears to declare as "Unpredictable" any instruction which
14771ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         generates more than one possible new value for r15.  Hence
14772ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         just assert.  The decoders themselves should check against
14773ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         all such instructions which are thusly Unpredictable, and
14774ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         decline to decode them.  Hence we should never get here if we
14775ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         have competing new values for r15, and hence it is safe to
14776ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assert here. */
14777ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert(dres.whatNext == Dis_Continue);
14778ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert(irsb->next == NULL);
14779b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      vassert(irsb->jumpkind == Ijk_Boring);
14780ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* If r15 is unconditionally written, terminate the block by
14781ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         jumping to it.  If it's conditionally written, still
14782ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         terminate the block (a shame, but we can't do side exits to
14783ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         arbitrary destinations), but first jump to the next
14784ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         instruction if the condition doesn't hold. */
14785ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* We can't use getIReg(15) to get the destination, since that
14786ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         will produce r15+8, which isn't what we want.  Must use
14787ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         llGetIReg(15) instead. */
14788ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (r15guard == IRTemp_INVALID) {
14789ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* unconditional */
14790ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else {
14791ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* conditional */
14792ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         stmt( IRStmt_Exit(
14793ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  unop(Iop_32to1,
14794ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       binop(Iop_Xor32,
14795ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             mkexpr(r15guard), mkU32(1))),
14796ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  r15kind,
14797663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  IRConst_U32(guest_R15_curr_instr_notENC + 4),
14798663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  OFFB_R15T
14799ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ));
14800ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
14801663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* This seems crazy, but we're required to finish the insn with
14802663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         a write to the guest PC.  As usual we rely on ir_opt to tidy
14803663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         up later. */
14804663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      llPutIReg(15, llGetIReg(15));
14805663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      dres.whatNext    = Dis_StopHere;
14806663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      dres.jk_StopHere = r15kind;
14807663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   } else {
14808663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* Set up the end-state in the normal way. */
14809663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      switch (dres.whatNext) {
14810663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case Dis_Continue:
14811663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            llPutIReg(15, mkU32(dres.len + guest_R15_curr_instr_notENC));
14812663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            break;
14813663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case Dis_ResteerU:
14814663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case Dis_ResteerC:
14815663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            llPutIReg(15, mkU32(dres.continueAt));
14816663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            break;
14817663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         case Dis_StopHere:
14818663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            break;
14819663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         default:
14820663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            vassert(0);
14821663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
14822ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
14823ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14824ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return dres;
14825ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14826ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  undef INSN_COND
14827ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  undef INSN
14828ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
14829ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14830ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14831ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
14832ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Disassemble a single Thumb2 instruction              ---*/
14833ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
14834ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14835b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic const UChar it_length_table[256]; /* fwds */
14836b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
14837ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* NB: in Thumb mode we do fetches of regs with getIRegT, which
14838ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   automagically adds 4 to fetches of r15.  However, writes to regs
14839ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   are done with putIRegT, which disallows writes to r15.  Hence any
14840ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   r15 writes and associated jumps have to be done "by hand". */
14841ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14842ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Disassemble a single Thumb instruction into IR.  The instruction is
14843ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   located in host memory at guest_instr, and has (decoded) guest IP
14844ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   of guest_R15_curr_instr_notENC, which will have been set before the
14845ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   call here. */
14846ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14847ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
14848ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownDisResult disInstr_THUMB_WRK (
14849ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             Bool         (*resteerOkFn) ( /*opaque*/void*, Addr64 ),
14850ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             Bool         resteerCisOk,
14851ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             void*        callback_opaque,
14852ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             UChar*       guest_instr,
14853ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             VexArchInfo* archinfo,
14854ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             VexAbiInfo*  abiinfo
14855ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          )
14856ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
14857ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* A macro to fish bits out of insn0.  There's also INSN1, to fish
14858ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      bits out of insn1, but that's defined only after the end of the
14859ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      16-bit insn decoder, so as to stop it mistakenly being used
14860ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      therein. */
14861ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  define INSN0(_bMax,_bMin)  SLICE_UInt(((UInt)insn0), (_bMax), (_bMin))
14862ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14863ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   DisResult dres;
14864663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UShort    insn0; /*  first 16 bits of the insn */
14865663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   UShort    insn1; /* second 16 bits of the insn */
14866ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //Bool      allow_VFP = False;
14867ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //UInt      hwcaps = archinfo->hwcaps;
14868ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   HChar     dis_buf[128];  // big enough to hold LDMIA etc text
14869ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14870ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Summary result of the ITxxx backwards analysis: False == safe
14871ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      but suboptimal. */
14872ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Bool guaranteedUnconditional = False;
14873ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14874ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* What insn variants are we supporting today? */
14875ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //allow_VFP  = (0 != (hwcaps & VEX_HWCAPS_ARM_VFP));
14876ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // etc etc
14877ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14878ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Set result defaults. */
14879663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   dres.whatNext    = Dis_Continue;
14880663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   dres.len         = 2;
14881663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   dres.continueAt  = 0;
14882663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   dres.jk_StopHere = Ijk_INVALID;
14883ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14884ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Set default actions for post-insn handling of writes to r15, if
14885ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      required. */
14886ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   r15written = False;
14887ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   r15guard   = IRTemp_INVALID; /* unconditional */
14888ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   r15kind    = Ijk_Boring;
14889ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14890ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Insns could be 2 or 4 bytes long.  Just get the first 16 bits at
14891ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      this point.  If we need the second 16, get them later.  We can't
14892ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      get them both out immediately because it risks a fault (very
14893ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      unlikely, but ..) if the second 16 bits aren't actually
14894ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      necessary. */
14895ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   insn0 = getUShortLittleEndianly( guest_instr );
14896663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   insn1 = 0; /* We'll get it later, once we know we need it. */
14897663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
14898663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* Similarly, will set this later. */
14899663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp old_itstate = IRTemp_INVALID;
14900ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14901ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (0) vex_printf("insn: 0x%x\n", insn0);
14902ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14903ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   DIP("\t(thumb) 0x%x:  ", (UInt)guest_R15_curr_instr_notENC);
14904ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14905ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(0 == (guest_R15_curr_instr_notENC & 1));
14906ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14907ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* ----------------------------------------------------------- */
14908ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Spot "Special" instructions (see comment at top of file). */
14909ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   {
14910ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UChar* code = (UChar*)guest_instr;
14911ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Spot the 16-byte preamble:
14912ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14913ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ea4f 0cfc  mov.w   ip, ip, ror #3
14914ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ea4f 3c7c  mov.w   ip, ip, ror #13
14915ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ea4f 7c7c  mov.w   ip, ip, ror #29
14916ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ea4f 4cfc  mov.w   ip, ip, ror #19
14917ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      */
14918ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt word1 = 0x0CFCEA4F;
14919ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt word2 = 0x3C7CEA4F;
14920ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt word3 = 0x7C7CEA4F;
14921ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt word4 = 0x4CFCEA4F;
14922ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (getUIntLittleEndianly(code+ 0) == word1 &&
14923ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          getUIntLittleEndianly(code+ 4) == word2 &&
14924ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          getUIntLittleEndianly(code+ 8) == word3 &&
14925ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          getUIntLittleEndianly(code+12) == word4) {
14926ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Got a "Special" instruction preamble.  Which one is it? */
14927ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         // 0x 0A 0A EA 4A
14928ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (getUIntLittleEndianly(code+16) == 0x0A0AEA4A
14929ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                               /* orr.w r10,r10,r10 */) {
14930ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* R3 = client_request ( R4 ) */
14931ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            DIP("r3 = client_request ( %%r4 )\n");
14932663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            llPutIReg(15, mkU32( (guest_R15_curr_instr_notENC + 20) | 1 ));
14933663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            dres.jk_StopHere = Ijk_ClientReq;
14934663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            dres.whatNext    = Dis_StopHere;
14935ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto decode_success;
14936ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
14937ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         else
14938ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         // 0x 0B 0B EA 4B
14939ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (getUIntLittleEndianly(code+16) == 0x0B0BEA4B
14940ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                               /* orr r11,r11,r11 */) {
14941ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* R3 = guest_NRADDR */
14942ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            DIP("r3 = guest_NRADDR\n");
14943ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            dres.len = 20;
14944ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            llPutIReg(3, IRExpr_Get( OFFB_NRADDR, Ity_I32 ));
14945ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto decode_success;
14946ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
14947ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         else
14948ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         // 0x 0C 0C EA 4C
14949ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (getUIntLittleEndianly(code+16) == 0x0C0CEA4C
14950ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                               /* orr r12,r12,r12 */) {
14951ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /*  branch-and-link-to-noredir R4 */
14952ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            DIP("branch-and-link-to-noredir r4\n");
14953ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            llPutIReg(14, mkU32( (guest_R15_curr_instr_notENC + 20) | 1 ));
14954663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            llPutIReg(15, getIRegT(4));
14955663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            dres.jk_StopHere = Ijk_NoRedir;
14956663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            dres.whatNext    = Dis_StopHere;
14957ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto decode_success;
14958ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
14959ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* We don't know what it is.  Set insn0 so decode_failure
14960ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            can print the insn following the Special-insn preamble. */
14961ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         insn0 = getUShortLittleEndianly(code+16);
14962ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto decode_failure;
14963ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /*NOTREACHED*/
14964ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
14965ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14966ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
14967ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14968ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* ----------------------------------------------------------- */
14969ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14970ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Main Thumb instruction decoder starts here.  It's a series of
14971ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switches which examine ever longer bit sequences at the MSB of
14972ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      the instruction word, first for 16-bit insns, then for 32-bit
14973ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      insns. */
14974ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14975ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* --- BEGIN ITxxx optimisation analysis --- */
14976ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* This is a crucial optimisation for the ITState boilerplate that
14977ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      follows.  Examine the 9 halfwords preceding this instruction,
14978ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      and if we are absolutely sure that none of them constitute an
14979ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      'it' instruction, then we can be sure that this instruction is
14980ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      not under the control of any 'it' instruction, and so
14981ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      guest_ITSTATE must be zero.  So write zero into ITSTATE right
14982ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      now, so that iropt can fold out almost all of the resulting
14983ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      junk.
14984ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14985ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      If we aren't sure, we can always safely skip this step.  So be a
14986ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      bit conservative about it: only poke around in the same page as
14987ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      this instruction, lest we get a fault from the previous page
14988ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      that would not otherwise have happened.  The saving grace is
14989ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      that such skipping is pretty rare -- it only happens,
14990ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      statistically, 18/4096ths of the time, so is judged unlikely to
14991ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      be a performance problems.
14992ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14993ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      FIXME: do better.  Take into account the number of insns covered
14994ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      by any IT insns we find, to rule out cases where an IT clearly
14995ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      cannot cover this instruction.  This would improve behaviour for
14996ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      branch targets immediately following an IT-guarded group that is
14997ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      not of full length.  Eg, (and completely ignoring issues of 16-
14998ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vs 32-bit insn length):
14999ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15000ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             ite cond
15001ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             insn1
15002ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             insn2
15003ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      label: insn3
15004ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             insn4
15005ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15006ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      The 'it' only conditionalises insn1 and insn2.  However, the
15007ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      current analysis is conservative and considers insn3 and insn4
15008ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      also possibly guarded.  Hence if 'label:' is the start of a hot
15009ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      loop we will get a big performance hit.
15010ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   */
15011ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   {
15012ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Summary result of this analysis: False == safe but
15013ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         suboptimal. */
15014ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert(guaranteedUnconditional == False);
15015ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15016ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt pc = guest_R15_curr_instr_notENC;
15017ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert(0 == (pc & 1));
15018ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15019ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt pageoff = pc & 0xFFF;
15020ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (pageoff >= 18) {
15021ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* It's safe to poke about in the 9 halfwords preceding this
15022ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            insn.  So, have a look at them. */
15023b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         guaranteedUnconditional = True; /* assume no 'it' insn found,
15024b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                            till we do */
15025ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         UShort* hwp = (UShort*)(HWord)pc;
15026ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         Int i;
15027ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         for (i = -1; i >= -9; i--) {
15028ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* We're in the same page.  (True, but commented out due
15029ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               to expense.) */
15030ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /*
15031ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vassert( ( ((UInt)(&hwp[i])) & 0xFFFFF000 )
15032ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      == ( pc & 0xFFFFF000 ) );
15033ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            */
15034ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* All valid IT instructions must have the form 0xBFxy,
15035b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               where x can be anything, but y must be nonzero.  Find
15036b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               the number of insns covered by it (1 .. 4) and check to
15037b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               see if it can possibly reach up to the instruction in
15038b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               question.  Some (x,y) combinations mean UNPREDICTABLE,
15039b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               and the table is constructed to be conservative by
15040b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               returning 4 for those cases, so the analysis is safe
15041b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               even if the code uses unpredictable IT instructions (in
15042b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               which case its authors are nuts, but hey.)  */
15043b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            UShort hwp_i = hwp[i];
15044b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            if (UNLIKELY((hwp_i & 0xFF00) == 0xBF00 && (hwp_i & 0xF) != 0)) {
15045b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               /* might be an 'it' insn. */
15046b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               /* # guarded insns */
15047b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               Int n_guarded = (Int)it_length_table[hwp_i & 0xFF];
15048b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               vassert(n_guarded >= 1 && n_guarded <= 4);
15049b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               if (n_guarded * 2 /* # guarded HWs, worst case */
15050b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                   > (-(i+1)))   /* -(i+1): # remaining HWs after the IT */
15051b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                   /* -(i+0) also seems to work, even though I think
15052b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                      it's wrong.  I don't understand that. */
15053b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                  guaranteedUnconditional = False;
15054ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
15055ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
15056ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
15057ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
15058ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
15059ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* --- END ITxxx optimisation analysis --- */
15060ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15061ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Generate the guarding condition for this insn, by examining
15062ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ITSTATE.  Assign it to condT.  Also, generate new
15063ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      values for ITSTATE ready for stuffing back into the
15064ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      guest state, but don't actually do the Put yet, since it will
15065ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      need to stuffed back in only after the instruction gets to a
15066ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      point where it is sure to complete.  Mostly we let the code at
15067ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      decode_success handle this, but in cases where the insn contains
15068ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      a side exit, we have to update them before the exit. */
15069ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15070ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* If the ITxxx optimisation analysis above could not prove that
15071ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      this instruction is guaranteed unconditional, we insert a
15072ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      lengthy IR preamble to compute the guarding condition at
15073ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      runtime.  If it can prove it (which obviously we hope is the
15074ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      normal case) then we insert a minimal preamble, which is
15075ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      equivalent to setting guest_ITSTATE to zero and then folding
15076ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      that through the full preamble (which completely disappears). */
15077ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15078ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp condT              = IRTemp_INVALID;
15079ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp cond_AND_notInIT_T = IRTemp_INVALID;
15080ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15081663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   IRTemp new_itstate        = IRTemp_INVALID;
15082663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vassert(old_itstate == IRTemp_INVALID);
15083663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
15084ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (guaranteedUnconditional) {
15085ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* BEGIN "partial eval { ITSTATE = 0; STANDARD_PREAMBLE; }" */
15086ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15087ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // ITSTATE = 0 :: I32
15088ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp z32 = newTemp(Ity_I32);
15089ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign(z32, mkU32(0));
15090ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      put_ITSTATE(z32);
15091ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15092ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // old_itstate = 0 :: I32
15093ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      //
15094ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // old_itstate = get_ITSTATE();
15095ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      old_itstate = z32; /* 0 :: I32 */
15096ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15097ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // new_itstate = old_itstate >> 8
15098ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      //             = 0 >> 8
15099ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      //             = 0 :: I32
15100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      //
15101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // new_itstate = newTemp(Ity_I32);
15102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // assign(new_itstate,
15103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      //        binop(Iop_Shr32, mkexpr(old_itstate), mkU8(8)));
15104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      new_itstate = z32;
15105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // ITSTATE = 0 :: I32(again)
15107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      //
15108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // put_ITSTATE(new_itstate);
15109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // condT1 = calc_cond_dyn( xor(and(old_istate,0xF0), 0xE0) )
15111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      //        = calc_cond_dyn( xor(0,0xE0) )
15112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      //        = calc_cond_dyn ( 0xE0 )
15113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      //        = 1 :: I32
15114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // Not that this matters, since the computed value is not used:
15115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // see condT folding below
15116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      //
15117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // IRTemp condT1 = newTemp(Ity_I32);
15118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // assign(condT1,
15119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      //        mk_armg_calculate_condition_dyn(
15120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      //           binop(Iop_Xor32,
15121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      //                 binop(Iop_And32, mkexpr(old_itstate), mkU32(0xF0)),
15122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      //                 mkU32(0xE0))
15123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      //       )
15124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // );
15125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // condT = 32to8(and32(old_itstate,0xF0)) == 0  ? 1  : condT1
15127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      //       = 32to8(and32(0,0xF0)) == 0  ? 1  : condT1
15128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      //       = 32to8(0) == 0  ? 1  : condT1
15129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      //       = 0 == 0  ? 1  : condT1
15130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      //       = 1
15131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      //
15132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // condT = newTemp(Ity_I32);
15133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // assign(condT, IRExpr_Mux0X(
15134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      //                  unop(Iop_32to8, binop(Iop_And32,
15135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      //                                        mkexpr(old_itstate),
15136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      //                                        mkU32(0xF0))),
15137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      //                  mkU32(1),
15138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      //                  mkexpr(condT1)
15139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      //       ));
15140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      condT = newTemp(Ity_I32);
15141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign(condT, mkU32(1));
15142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // notInITt = xor32(and32(old_itstate, 1), 1)
15144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      //          = xor32(and32(0, 1), 1)
15145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      //          = xor32(0, 1)
15146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      //          = 1 :: I32
15147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      //
15148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // IRTemp notInITt = newTemp(Ity_I32);
15149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // assign(notInITt,
15150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      //        binop(Iop_Xor32,
15151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      //              binop(Iop_And32, mkexpr(old_itstate), mkU32(1)),
15152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      //              mkU32(1)));
15153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // cond_AND_notInIT_T = and32(notInITt, condT)
15155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      //                    = and32(1, 1)
15156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      //                    = 1
15157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      //
15158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // cond_AND_notInIT_T = newTemp(Ity_I32);
15159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // assign(cond_AND_notInIT_T,
15160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      //        binop(Iop_And32, mkexpr(notInITt), mkexpr(condT)));
15161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      cond_AND_notInIT_T = condT; /* 1 :: I32 */
15162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* END "partial eval { ITSTATE = 0; STANDARD_PREAMBLE; }" */
15164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
15165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* BEGIN { STANDARD PREAMBLE; } */
15166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      old_itstate = get_ITSTATE();
15168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      new_itstate = newTemp(Ity_I32);
15170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign(new_itstate,
15171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             binop(Iop_Shr32, mkexpr(old_itstate), mkU8(8)));
15172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      put_ITSTATE(new_itstate);
15174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Same strategy as for ARM insns: generate a condition
15176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         temporary at this point (or IRTemp_INVALID, meaning
15177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         unconditional).  We leave it to lower-level instruction
15178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         decoders to decide whether they can generate straight-line
15179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         code, or whether they must generate a side exit before the
15180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         instruction.  condT :: Ity_I32 and is always either zero or
15181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         one. */
15182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp condT1 = newTemp(Ity_I32);
15183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign(condT1,
15184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             mk_armg_calculate_condition_dyn(
15185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                binop(Iop_Xor32,
15186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      binop(Iop_And32, mkexpr(old_itstate), mkU32(0xF0)),
15187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      mkU32(0xE0))
15188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            )
15189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      );
15190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* This is a bit complex, but needed to make Memcheck understand
15192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         that, if the condition in old_itstate[7:4] denotes AL (that
15193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         is, if this instruction is to be executed unconditionally),
15194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         then condT does not depend on the results of calling the
15195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         helper.
15196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         We test explicitly for old_itstate[7:4] == AL ^ 0xE, and in
15198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         that case set condT directly to 1.  Else we use the results
15199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         of the helper.  Since old_itstate is always defined and
15200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         because Memcheck does lazy V-bit propagation through Mux0X,
15201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         this will cause condT to always be a defined 1 if the
15202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         condition is 'AL'.  From an execution semantics point of view
15203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         this is irrelevant since we're merely duplicating part of the
15204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         behaviour of the helper.  But it makes it clear to Memcheck,
15205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         in this case, that condT does not in fact depend on the
15206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         contents of the condition code thunk.  Without it, we get
15207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         quite a lot of false errors.
15208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         So, just to clarify: from a straight semantics point of view,
15210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         we can simply do "assign(condT, mkexpr(condT1))", and the
15211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         simulator still runs fine.  It's just that we get loads of
15212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         false errors from Memcheck. */
15213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      condT = newTemp(Ity_I32);
15214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign(condT, IRExpr_Mux0X(
15215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       unop(Iop_32to8, binop(Iop_And32,
15216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                             mkexpr(old_itstate),
15217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                             mkU32(0xF0))),
15218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       mkU32(1),
15219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       mkexpr(condT1)
15220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ));
15221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Something we don't have in ARM: generate a 0 or 1 value
15223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         indicating whether or not we are in an IT block (NB: 0 = in
15224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IT block, 1 = not in IT block).  This is used to gate
15225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         condition code updates in 16-bit Thumb instructions. */
15226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp notInITt = newTemp(Ity_I32);
15227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign(notInITt,
15228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             binop(Iop_Xor32,
15229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   binop(Iop_And32, mkexpr(old_itstate), mkU32(1)),
15230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   mkU32(1)));
15231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Compute 'condT && notInITt' -- that is, the instruction is
15233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         going to execute, and we're not in an IT block.  This is the
15234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         gating condition for updating condition codes in 16-bit Thumb
15235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         instructions, except for CMP, CMN and TST. */
15236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      cond_AND_notInIT_T = newTemp(Ity_I32);
15237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign(cond_AND_notInIT_T,
15238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             binop(Iop_And32, mkexpr(notInITt), mkexpr(condT)));
15239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* END { STANDARD PREAMBLE; } */
15240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
15241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* At this point:
15244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      * ITSTATE has been updated
15245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      * condT holds the guarding condition for this instruction (0 or 1),
15246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      * notInITt is 1 if we're in "normal" code, 0 if in an IT block
15247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      * cond_AND_notInIT_T is the AND of the above two.
15248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      If the instruction proper can't trap, then there's nothing else
15250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      to do w.r.t. ITSTATE -- just go and and generate IR for the
15251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      insn, taking into account the guarding condition.
15252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      If, however, the instruction might trap, then we must back up
15254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ITSTATE to the old value, and re-update it after the potentially
15255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      trapping IR section.  A trap can happen either via a memory
15256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      reference or because we need to throw SIGILL.
15257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      If an instruction has a side exit, we need to be sure that any
15259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ITSTATE backup is re-updated before the side exit.
15260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   */
15261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* ----------------------------------------------------------- */
15263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* --                                                       -- */
15264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* -- Thumb 16-bit integer instructions                     -- */
15265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* --                                                       -- */
15266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* -- IMPORTANT: references to insn1 or INSN1 are           -- */
15267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* --            not allowed in this section                -- */
15268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* --                                                       -- */
15269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* ----------------------------------------------------------- */
15270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* 16-bit instructions inside an IT block, apart from CMP, CMN and
15272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      TST, do not set the condition codes.  Hence we must dynamically
15273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      test for this case for every condition code update. */
15274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IROp   anOp   = Iop_INVALID;
15276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   HChar* anOpNm = NULL;
15277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* ================ 16-bit 15:6 cases ================ */
15279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (INSN0(15,6)) {
15281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x10a:   // CMP
15283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x10b: { // CMN
15284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* ---------------- CMP Rn, Rm ---------------- */
15285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Bool   isCMN = INSN0(15,6) == 0x10b;
15286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt   rN    = INSN0(2,0);
15287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt   rM    = INSN0(5,3);
15288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp argL  = newTemp(Ity_I32);
15289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp argR  = newTemp(Ity_I32);
15290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( argL, getIRegT(rN) );
15291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( argR, getIRegT(rM) );
15292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Update flags regardless of whether in an IT block or not. */
15293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      setFlags_D1_D2( isCMN ? ARMG_CC_OP_ADD : ARMG_CC_OP_SUB,
15294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      argL, argR, condT );
15295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("%s r%u, r%u\n", isCMN ? "cmn" : "cmp", rN, rM);
15296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      goto decode_success;
15297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
15298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x108: {
15300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* ---------------- TST Rn, Rm ---------------- */
15301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt   rN   = INSN0(2,0);
15302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt   rM   = INSN0(5,3);
15303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp oldC = newTemp(Ity_I32);
15304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp oldV = newTemp(Ity_I32);
15305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp res  = newTemp(Ity_I32);
15306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( oldC, mk_armg_calculate_flag_c() );
15307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( oldV, mk_armg_calculate_flag_v() );
15308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( res,  binop(Iop_And32, getIRegT(rN), getIRegT(rM)) );
15309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Update flags regardless of whether in an IT block or not. */
15310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      setFlags_D1_D2_ND( ARMG_CC_OP_LOGIC, res, oldC, oldV, condT );
15311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("tst r%u, r%u\n", rN, rM);
15312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      goto decode_success;
15313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
15314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x109: {
15316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* ---------------- NEGS Rd, Rm ---------------- */
15317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Rd = -Rm */
15318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt   rM   = INSN0(5,3);
15319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt   rD   = INSN0(2,0);
15320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp arg  = newTemp(Ity_I32);
15321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp zero = newTemp(Ity_I32);
15322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign(arg, getIRegT(rM));
15323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign(zero, mkU32(0));
15324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // rD can never be r15
15325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putIRegT(rD, binop(Iop_Sub32, mkexpr(zero), mkexpr(arg)), condT);
15326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      setFlags_D1_D2( ARMG_CC_OP_SUB, zero, arg, cond_AND_notInIT_T);
15327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("negs r%u, r%u\n", rD, rM);
15328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      goto decode_success;
15329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
15330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x10F: {
15332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* ---------------- MVNS Rd, Rm ---------------- */
15333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Rd = ~Rm */
15334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt   rM   = INSN0(5,3);
15335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt   rD   = INSN0(2,0);
15336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp oldV = newTemp(Ity_I32);
15337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp oldC = newTemp(Ity_I32);
15338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp res  = newTemp(Ity_I32);
15339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( oldV, mk_armg_calculate_flag_v() );
15340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( oldC, mk_armg_calculate_flag_c() );
15341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign(res, unop(Iop_Not32, getIRegT(rM)));
15342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // rD can never be r15
15343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putIRegT(rD, mkexpr(res), condT);
15344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      setFlags_D1_D2_ND( ARMG_CC_OP_LOGIC, res, oldC, oldV,
15345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         cond_AND_notInIT_T );
15346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("mvns r%u, r%u\n", rD, rM);
15347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      goto decode_success;
15348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
15349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x10C:
15351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* ---------------- ORRS Rd, Rm ---------------- */
15352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      anOp = Iop_Or32; anOpNm = "orr"; goto and_orr_eor_mul;
15353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x100:
15354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* ---------------- ANDS Rd, Rm ---------------- */
15355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      anOp = Iop_And32; anOpNm = "and"; goto and_orr_eor_mul;
15356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x101:
15357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* ---------------- EORS Rd, Rm ---------------- */
15358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      anOp = Iop_Xor32; anOpNm = "eor"; goto and_orr_eor_mul;
15359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x10d:
15360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* ---------------- MULS Rd, Rm ---------------- */
15361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      anOp = Iop_Mul32; anOpNm = "mul"; goto and_orr_eor_mul;
15362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   and_orr_eor_mul: {
15363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Rd = Rd `op` Rm */
15364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt   rM   = INSN0(5,3);
15365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt   rD   = INSN0(2,0);
15366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp res  = newTemp(Ity_I32);
15367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp oldV = newTemp(Ity_I32);
15368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp oldC = newTemp(Ity_I32);
15369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( oldV, mk_armg_calculate_flag_v() );
15370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( oldC, mk_armg_calculate_flag_c() );
15371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( res, binop(anOp, getIRegT(rD), getIRegT(rM) ));
15372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // not safe to read guest state after here
15373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // rD can never be r15
15374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putIRegT(rD, mkexpr(res), condT);
15375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      setFlags_D1_D2_ND( ARMG_CC_OP_LOGIC, res, oldC, oldV,
15376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         cond_AND_notInIT_T );
15377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("%s r%u, r%u\n", anOpNm, rD, rM);
15378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      goto decode_success;
15379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
15380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x10E: {
15382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* ---------------- BICS Rd, Rm ---------------- */
15383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Rd = Rd & ~Rm */
15384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt   rM   = INSN0(5,3);
15385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt   rD   = INSN0(2,0);
15386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp res  = newTemp(Ity_I32);
15387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp oldV = newTemp(Ity_I32);
15388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp oldC = newTemp(Ity_I32);
15389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( oldV, mk_armg_calculate_flag_v() );
15390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( oldC, mk_armg_calculate_flag_c() );
15391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( res, binop(Iop_And32, getIRegT(rD),
15392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                    unop(Iop_Not32, getIRegT(rM) )));
15393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // not safe to read guest state after here
15394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // rD can never be r15
15395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putIRegT(rD, mkexpr(res), condT);
15396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      setFlags_D1_D2_ND( ARMG_CC_OP_LOGIC, res, oldC, oldV,
15397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         cond_AND_notInIT_T );
15398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("bics r%u, r%u\n", rD, rM);
15399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      goto decode_success;
15400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
15401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x105: {
15403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* ---------------- ADCS Rd, Rm ---------------- */
15404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Rd = Rd + Rm + oldC */
15405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt   rM   = INSN0(5,3);
15406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt   rD   = INSN0(2,0);
15407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp argL = newTemp(Ity_I32);
15408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp argR = newTemp(Ity_I32);
15409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp oldC = newTemp(Ity_I32);
15410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp res  = newTemp(Ity_I32);
15411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign(argL, getIRegT(rD));
15412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign(argR, getIRegT(rM));
15413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign(oldC, mk_armg_calculate_flag_c());
15414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign(res, binop(Iop_Add32,
15415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        binop(Iop_Add32, mkexpr(argL), mkexpr(argR)),
15416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        mkexpr(oldC)));
15417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // rD can never be r15
15418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putIRegT(rD, mkexpr(res), condT);
15419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      setFlags_D1_D2_ND( ARMG_CC_OP_ADC, argL, argR, oldC,
15420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         cond_AND_notInIT_T );
15421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("adcs r%u, r%u\n", rD, rM);
15422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      goto decode_success;
15423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
15424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x106: {
15426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* ---------------- SBCS Rd, Rm ---------------- */
15427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Rd = Rd - Rm - (oldC ^ 1) */
15428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt   rM   = INSN0(5,3);
15429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt   rD   = INSN0(2,0);
15430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp argL = newTemp(Ity_I32);
15431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp argR = newTemp(Ity_I32);
15432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp oldC = newTemp(Ity_I32);
15433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp res  = newTemp(Ity_I32);
15434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign(argL, getIRegT(rD));
15435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign(argR, getIRegT(rM));
15436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign(oldC, mk_armg_calculate_flag_c());
15437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign(res, binop(Iop_Sub32,
15438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        binop(Iop_Sub32, mkexpr(argL), mkexpr(argR)),
15439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        binop(Iop_Xor32, mkexpr(oldC), mkU32(1))));
15440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // rD can never be r15
15441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putIRegT(rD, mkexpr(res), condT);
15442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      setFlags_D1_D2_ND( ARMG_CC_OP_SBB, argL, argR, oldC,
15443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         cond_AND_notInIT_T );
15444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("sbcs r%u, r%u\n", rD, rM);
15445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      goto decode_success;
15446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
15447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x2CB: {
15449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* ---------------- UXTB Rd, Rm ---------------- */
15450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Rd = 8Uto32(Rm) */
15451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt rM = INSN0(5,3);
15452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt rD = INSN0(2,0);
15453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putIRegT(rD, binop(Iop_And32, getIRegT(rM), mkU32(0xFF)),
15454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   condT);
15455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("uxtb r%u, r%u\n", rD, rM);
15456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      goto decode_success;
15457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
15458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x2C9: {
15460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* ---------------- SXTB Rd, Rm ---------------- */
15461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Rd = 8Sto32(Rm) */
15462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt rM = INSN0(5,3);
15463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt rD = INSN0(2,0);
15464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putIRegT(rD, binop(Iop_Sar32,
15465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         binop(Iop_Shl32, getIRegT(rM), mkU8(24)),
15466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         mkU8(24)),
15467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   condT);
15468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("sxtb r%u, r%u\n", rD, rM);
15469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      goto decode_success;
15470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
15471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x2CA: {
15473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* ---------------- UXTH Rd, Rm ---------------- */
15474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Rd = 16Uto32(Rm) */
15475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt rM = INSN0(5,3);
15476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt rD = INSN0(2,0);
15477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putIRegT(rD, binop(Iop_And32, getIRegT(rM), mkU32(0xFFFF)),
15478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   condT);
15479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("uxth r%u, r%u\n", rD, rM);
15480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      goto decode_success;
15481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
15482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x2C8: {
15484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* ---------------- SXTH Rd, Rm ---------------- */
15485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Rd = 16Sto32(Rm) */
15486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt rM = INSN0(5,3);
15487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt rD = INSN0(2,0);
15488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putIRegT(rD, binop(Iop_Sar32,
15489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         binop(Iop_Shl32, getIRegT(rM), mkU8(16)),
15490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         mkU8(16)),
15491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   condT);
15492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("sxth r%u, r%u\n", rD, rM);
15493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      goto decode_success;
15494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
15495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x102:   // LSLS
15497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x103:   // LSRS
15498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x104:   // ASRS
15499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x107: { // RORS
15500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* ---------------- LSLS Rs, Rd ---------------- */
15501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* ---------------- LSRS Rs, Rd ---------------- */
15502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* ---------------- ASRS Rs, Rd ---------------- */
15503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* ---------------- RORS Rs, Rd ---------------- */
15504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Rd = Rd `op` Rs, and set flags */
15505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt   rS   = INSN0(5,3);
15506ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt   rD   = INSN0(2,0);
15507ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp oldV = newTemp(Ity_I32);
15508ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp rDt  = newTemp(Ity_I32);
15509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp rSt  = newTemp(Ity_I32);
15510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp res  = newTemp(Ity_I32);
15511ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp resC = newTemp(Ity_I32);
15512ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HChar* wot  = "???";
15513ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign(rSt, getIRegT(rS));
15514ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign(rDt, getIRegT(rD));
15515ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign(oldV, mk_armg_calculate_flag_v());
15516ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Does not appear to be the standard 'how' encoding. */
15517ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch (INSN0(15,6)) {
15518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case 0x102:
15519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            compute_result_and_C_after_LSL_by_reg(
15520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               dis_buf, &res, &resC, rDt, rSt, rD, rS
15521ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            );
15522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            wot = "lsl";
15523ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
15524ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case 0x103:
15525ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            compute_result_and_C_after_LSR_by_reg(
15526ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               dis_buf, &res, &resC, rDt, rSt, rD, rS
15527ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            );
15528ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            wot = "lsr";
15529ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
15530ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case 0x104:
15531ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            compute_result_and_C_after_ASR_by_reg(
15532ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               dis_buf, &res, &resC, rDt, rSt, rD, rS
15533ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            );
15534ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            wot = "asr";
15535ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
15536ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case 0x107:
15537ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            compute_result_and_C_after_ROR_by_reg(
15538ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               dis_buf, &res, &resC, rDt, rSt, rD, rS
15539ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            );
15540ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            wot = "ror";
15541ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
15542ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         default:
15543ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /*NOTREACHED*/vassert(0);
15544ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
15545ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // not safe to read guest state after this point
15546ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putIRegT(rD, mkexpr(res), condT);
15547ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      setFlags_D1_D2_ND( ARMG_CC_OP_LOGIC, res, resC, oldV,
15548ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         cond_AND_notInIT_T );
15549ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("%ss r%u, r%u\n", wot, rS, rD);
15550ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      goto decode_success;
15551ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
15552ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15553ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x2E8:   // REV
15554ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x2E9: { // REV16
15555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* ---------------- REV   Rd, Rm ---------------- */
15556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* ---------------- REV16 Rd, Rm ---------------- */
15557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt rM = INSN0(5,3);
15558ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt rD = INSN0(2,0);
15559ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Bool isREV = INSN0(15,6) == 0x2E8;
15560ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp arg = newTemp(Ity_I32);
15561ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign(arg, getIRegT(rM));
15562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp res = isREV ? gen_REV(arg) : gen_REV16(arg);
15563ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putIRegT(rD, mkexpr(res), condT);
15564ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("rev%s r%u, r%u\n", isREV ? "" : "16", rD, rM);
15565ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      goto decode_success;
15566ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
15567ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15568ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   default:
15569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break; /* examine the next shortest prefix */
15570ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15571ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
15572ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15573ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15574ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* ================ 16-bit 15:7 cases ================ */
15575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (INSN0(15,7)) {
15577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case BITS9(1,0,1,1,0,0,0,0,0): {
15579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* ------------ ADD SP, #imm7 * 4 ------------ */
15580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt uimm7 = INSN0(6,0);
15581ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putIRegT(13, binop(Iop_Add32, getIRegT(13), mkU32(uimm7 * 4)),
15582ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   condT);
15583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("add sp, #%u\n", uimm7 * 4);
15584ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      goto decode_success;
15585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
15586ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15587ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case BITS9(1,0,1,1,0,0,0,0,1): {
15588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* ------------ SUB SP, #imm7 * 4 ------------ */
15589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt uimm7 = INSN0(6,0);
15590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putIRegT(13, binop(Iop_Sub32, getIRegT(13), mkU32(uimm7 * 4)),
15591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   condT);
15592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("sub sp, #%u\n", uimm7 * 4);
15593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      goto decode_success;
15594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
15595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case BITS9(0,1,0,0,0,1,1,1,0): {
15597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* ---------------- BX rM ---------------- */
15598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Branch to reg, and optionally switch modes.  Reg contains a
15599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         suitably encoded address therefore (w CPSR.T at the bottom).
15600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         Have to special-case r15, as usual. */
15601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt rM = (INSN0(6,6) << 3) | INSN0(5,3);
15602ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (BITS3(0,0,0) == INSN0(2,0)) {
15603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp dst = newTemp(Ity_I32);
15604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         gen_SIGILL_T_if_in_but_NLI_ITBlock(old_itstate, new_itstate);
15605ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         mk_skip_over_T16_if_cond_is_false(condT);
15606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         condT = IRTemp_INVALID;
15607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         // now uncond
15608ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (rM <= 14) {
15609ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            assign( dst, getIRegT(rM) );
15610ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
15611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vassert(rM == 15);
15612ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            assign( dst, mkU32(guest_R15_curr_instr_notENC + 4) );
15613ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
15614663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         llPutIReg(15, mkexpr(dst));
15615663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         dres.jk_StopHere = rM == 14 ? Ijk_Ret : Ijk_Boring;
15616663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         dres.whatNext    = Dis_StopHere;
15617ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("bx r%u (possibly switch to ARM mode)\n", rM);
15618ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto decode_success;
15619ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
15620ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
15621ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
15622ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15623ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* ---------------- BLX rM ---------------- */
15624ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Branch and link to interworking address in rM. */
15625ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case BITS9(0,1,0,0,0,1,1,1,1): {
15626ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (BITS3(0,0,0) == INSN0(2,0)) {
15627ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         UInt rM = (INSN0(6,6) << 3) | INSN0(5,3);
15628ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp dst = newTemp(Ity_I32);
15629ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (rM <= 14) {
15630ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            gen_SIGILL_T_if_in_but_NLI_ITBlock(old_itstate, new_itstate);
15631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            mk_skip_over_T16_if_cond_is_false(condT);
15632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            condT = IRTemp_INVALID;
15633ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            // now uncond
15634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* We're returning to Thumb code, hence "| 1" */
15635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            assign( dst, getIRegT(rM) );
15636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            putIRegT( 14, mkU32( (guest_R15_curr_instr_notENC + 2) | 1 ),
15637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          IRTemp_INVALID );
15638663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            llPutIReg(15, mkexpr(dst));
15639663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            dres.jk_StopHere = Ijk_Call;
15640663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            dres.whatNext    = Dis_StopHere;
15641ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            DIP("blx r%u (possibly switch to ARM mode)\n", rM);
15642ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto decode_success;
15643ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
15644ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* else unpredictable, fall through */
15645ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
15646ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
15647ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
15648ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15649ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   default:
15650ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break; /* examine the next shortest prefix */
15651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15652ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
15653ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15654ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15655ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* ================ 16-bit 15:8 cases ================ */
15656ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15657ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (INSN0(15,8)) {
15658ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15659ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case BITS8(1,1,0,1,1,1,1,1): {
15660ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* ---------------- SVC ---------------- */
15661ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt imm8 = INSN0(7,0);
15662ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (imm8 == 0) {
15663ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* A syscall.  We can't do this conditionally, hence: */
15664ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         mk_skip_over_T16_if_cond_is_false( condT );
15665ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         // FIXME: what if we have to back up and restart this insn?
15666ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         // then ITSTATE will be wrong (we'll have it as "used")
15667ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         // when it isn't.  Correct is to save ITSTATE in a
15668ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         // stash pseudo-reg, and back up from that if we have to
15669ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         // restart.
15670ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         // uncond after here
15671663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         llPutIReg(15, mkU32( (guest_R15_curr_instr_notENC + 2) | 1 ));
15672663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         dres.jk_StopHere = Ijk_Sys_syscall;
15673663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         dres.whatNext    = Dis_StopHere;
15674ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("svc #0x%08x\n", imm8);
15675ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto decode_success;
15676ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
15677ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* else fall through */
15678ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
15679ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
15680ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15681ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case BITS8(0,1,0,0,0,1,0,0): {
15682ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* ---------------- ADD(HI) Rd, Rm ---------------- */
15683ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt h1 = INSN0(7,7);
15684ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt h2 = INSN0(6,6);
15685ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt rM = (h2 << 3) | INSN0(5,3);
15686ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt rD = (h1 << 3) | INSN0(2,0);
15687ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      //if (h1 == 0 && h2 == 0) { // Original T1 was more restrictive
15688ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (rD == 15 && rM == 15) {
15689ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         // then it's invalid
15690ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else {
15691ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp res = newTemp(Ity_I32);
15692ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( res, binop(Iop_Add32, getIRegT(rD), getIRegT(rM) ));
15693ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (rD != 15) {
15694ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            putIRegT( rD, mkexpr(res), condT );
15695ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
15696ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* Only allowed outside or last-in IT block; SIGILL if not so. */
15697ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            gen_SIGILL_T_if_in_but_NLI_ITBlock(old_itstate, new_itstate);
15698ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* jump over insn if not selected */
15699ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            mk_skip_over_T16_if_cond_is_false(condT);
15700ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            condT = IRTemp_INVALID;
15701ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            // now uncond
15702ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* non-interworking branch */
15703ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            irsb->next = binop(Iop_Or32, mkexpr(res), mkU32(1));
15704ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            irsb->jumpkind = Ijk_Boring;
15705ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            dres.whatNext = Dis_StopHere;
15706ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
15707ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("add(hi) r%u, r%u\n", rD, rM);
15708ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto decode_success;
15709ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
15710ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
15711ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
15712ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15713ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case BITS8(0,1,0,0,0,1,0,1): {
15714ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* ---------------- CMP(HI) Rd, Rm ---------------- */
15715ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt h1 = INSN0(7,7);
15716ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt h2 = INSN0(6,6);
15717ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt rM = (h2 << 3) | INSN0(5,3);
15718ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt rN = (h1 << 3) | INSN0(2,0);
15719ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (h1 != 0 || h2 != 0) {
15720ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp argL  = newTemp(Ity_I32);
15721ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp argR  = newTemp(Ity_I32);
15722ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( argL, getIRegT(rN) );
15723ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( argR, getIRegT(rM) );
15724ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Update flags regardless of whether in an IT block or not. */
15725ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         setFlags_D1_D2( ARMG_CC_OP_SUB, argL, argR, condT );
15726ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("cmphi r%u, r%u\n", rN, rM);
15727ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto decode_success;
15728ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
15729ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
15730ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
15731ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15732ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case BITS8(0,1,0,0,0,1,1,0): {
15733ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* ---------------- MOV(HI) Rd, Rm ---------------- */
15734ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt h1 = INSN0(7,7);
15735ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt h2 = INSN0(6,6);
15736ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt rM = (h2 << 3) | INSN0(5,3);
15737ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt rD = (h1 << 3) | INSN0(2,0);
15738ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* The old ARM ARM seems to disallow the case where both Rd and
15739ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         Rm are "low" registers, but newer versions allow it. */
15740ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (1 /*h1 != 0 || h2 != 0*/) {
15741ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp val = newTemp(Ity_I32);
15742ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( val, getIRegT(rM) );
15743ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (rD != 15) {
15744ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            putIRegT( rD, mkexpr(val), condT );
15745ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
15746ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* Only allowed outside or last-in IT block; SIGILL if not so. */
15747ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            gen_SIGILL_T_if_in_but_NLI_ITBlock(old_itstate, new_itstate);
15748ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* jump over insn if not selected */
15749ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            mk_skip_over_T16_if_cond_is_false(condT);
15750ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            condT = IRTemp_INVALID;
15751ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            // now uncond
15752ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* non-interworking branch */
15753663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            llPutIReg(15, binop(Iop_Or32, mkexpr(val), mkU32(1)));
15754663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            dres.jk_StopHere = rM == 14 ? Ijk_Ret : Ijk_Boring;
15755663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            dres.whatNext    = Dis_StopHere;
15756ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
15757ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("mov r%u, r%u\n", rD, rM);
15758ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto decode_success;
15759ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
15760ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
15761ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
15762ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15763ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case BITS8(1,0,1,1,1,1,1,1): {
15764ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* ---------------- IT (if-then) ---------------- */
15765ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt firstcond = INSN0(7,4);
15766ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt mask = INSN0(3,0);
15767ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt newITSTATE = 0;
15768ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* This is the ITSTATE represented as described in
15769ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         libvex_guest_arm.h.  It is not the ARM ARM representation. */
15770ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UChar c1 = '.';
15771ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UChar c2 = '.';
15772ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UChar c3 = '.';
15773ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Bool valid = compute_ITSTATE( &newITSTATE, &c1, &c2, &c3,
15774ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                    firstcond, mask );
15775ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (valid && firstcond != 0xF/*NV*/) {
15776ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Not allowed in an IT block; SIGILL if so. */
15777ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         gen_SIGILL_T_if_in_ITBlock(old_itstate, new_itstate);
15778ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15779ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp t = newTemp(Ity_I32);
15780ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign(t, mkU32(newITSTATE));
15781ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         put_ITSTATE(t);
15782ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15783ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("it%c%c%c %s\n", c1, c2, c3, nCC(firstcond));
15784ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto decode_success;
15785ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
15786ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
15787ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
15788ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15789ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case BITS8(1,0,1,1,0,0,0,1):
15790ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case BITS8(1,0,1,1,0,0,1,1):
15791ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case BITS8(1,0,1,1,1,0,0,1):
15792ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case BITS8(1,0,1,1,1,0,1,1): {
15793ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* ---------------- CB{N}Z ---------------- */
15794ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt rN    = INSN0(2,0);
15795ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt bOP   = INSN0(11,11);
15796ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt imm32 = (INSN0(9,9) << 6) | (INSN0(7,3) << 1);
15797ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      gen_SIGILL_T_if_in_ITBlock(old_itstate, new_itstate);
15798ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* It's a conditional branch forward. */
15799ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp kond = newTemp(Ity_I1);
15800ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( kond, binop(bOP ? Iop_CmpNE32 : Iop_CmpEQ32,
15801ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          getIRegT(rN), mkU32(0)) );
15802ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15803ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert(0 == (guest_R15_curr_instr_notENC & 1));
15804ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Looks like the nearest insn we can branch to is the one after
15805ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         next.  That makes sense, as there's no point in being able to
15806ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         encode a conditional branch to the next instruction. */
15807ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt dst = (guest_R15_curr_instr_notENC + 4 + imm32) | 1;
15808ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      stmt(IRStmt_Exit( mkexpr(kond),
15809ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        Ijk_Boring,
15810663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                        IRConst_U32(toUInt(dst)),
15811663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                        OFFB_R15T ));
15812ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("cb%s r%u, 0x%x\n", bOP ? "nz" : "z", rN, dst - 1);
15813ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      goto decode_success;
15814ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
15815ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15816ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   default:
15817ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break; /* examine the next shortest prefix */
15818ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15819ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
15820ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15821ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15822ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* ================ 16-bit 15:9 cases ================ */
15823ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15824ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (INSN0(15,9)) {
15825ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15826ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case BITS7(1,0,1,1,0,1,0): {
15827ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* ---------------- PUSH ---------------- */
15828ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* This is a bit like STMxx, but way simpler. Complications we
15829ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         don't have to deal with:
15830ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         * SP being one of the transferred registers
15831ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         * direction (increment vs decrement)
15832ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         * before-vs-after-ness
15833ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      */
15834ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Int  i, nRegs;
15835ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt bitR    = INSN0(8,8);
15836ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt regList = INSN0(7,0);
15837ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (bitR) regList |= (1 << 14);
15838ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15839663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* At least one register must be transferred, else result is
15840663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UNPREDICTABLE. */
15841ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (regList != 0) {
15842ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Since we can't generate a guaranteed non-trapping IR
15843ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            sequence, (1) jump over the insn if it is gated false, and
15844ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            (2) back out the ITSTATE update. */
15845ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         mk_skip_over_T16_if_cond_is_false(condT);
15846ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         condT = IRTemp_INVALID;
15847ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         put_ITSTATE(old_itstate);
15848ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         // now uncond
15849ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15850ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         nRegs = 0;
15851ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         for (i = 0; i < 16; i++) {
15852ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if ((regList & (1 << i)) != 0)
15853ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               nRegs++;
15854ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
15855663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         vassert(nRegs >= 1 && nRegs <= 9);
15856ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15857ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Move SP down first of all, so we're "covered".  And don't
15858ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            mess with its alignment. */
15859ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp newSP = newTemp(Ity_I32);
15860ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign(newSP, binop(Iop_Sub32, getIRegT(13), mkU32(4 * nRegs)));
15861ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putIRegT(13, mkexpr(newSP), IRTemp_INVALID);
15862ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15863ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Generate a transfer base address as a forced-aligned
15864ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            version of the final SP value. */
15865ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp base = newTemp(Ity_I32);
15866ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign(base, binop(Iop_And32, mkexpr(newSP), mkU32(~3)));
15867ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15868ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Now the transfers */
15869ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         nRegs = 0;
15870ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         for (i = 0; i < 16; i++) {
15871ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if ((regList & (1 << i)) != 0) {
15872ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               storeLE( binop(Iop_Add32, mkexpr(base), mkU32(4 * nRegs)),
15873ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        getIRegT(i) );
15874ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               nRegs++;
15875ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
15876ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
15877ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15878ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Reinstate the ITSTATE update. */
15879ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         put_ITSTATE(new_itstate);
15880ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15881ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("push {%s0x%04x}\n", bitR ? "lr," : "", regList & 0xFF);
15882ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto decode_success;
15883ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
15884ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
15885ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
15886ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15887ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case BITS7(1,0,1,1,1,1,0): {
15888ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* ---------------- POP ---------------- */
15889ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Int  i, nRegs;
15890ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt bitR    = INSN0(8,8);
15891ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt regList = INSN0(7,0);
15892ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15893663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* At least one register must be transferred, else result is
15894663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         UNPREDICTABLE. */
15895ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (regList != 0 || bitR) {
15896ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Since we can't generate a guaranteed non-trapping IR
15897ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            sequence, (1) jump over the insn if it is gated false, and
15898ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            (2) back out the ITSTATE update. */
15899ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         mk_skip_over_T16_if_cond_is_false(condT);
15900ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         condT = IRTemp_INVALID;
15901ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         put_ITSTATE(old_itstate);
15902ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         // now uncond
15903ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15904ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         nRegs = 0;
15905ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         for (i = 0; i < 8; i++) {
15906ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if ((regList & (1 << i)) != 0)
15907ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               nRegs++;
15908ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
15909663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         vassert(nRegs >= 0 && nRegs <= 8);
15910ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(bitR == 0 || bitR == 1);
15911ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15912ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp oldSP = newTemp(Ity_I32);
15913ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign(oldSP, getIRegT(13));
15914ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15915ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Generate a transfer base address as a forced-aligned
15916ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            version of the original SP value. */
15917ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp base = newTemp(Ity_I32);
15918ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign(base, binop(Iop_And32, mkexpr(oldSP), mkU32(~3)));
15919ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15920ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Compute a new value for SP, but don't install it yet, so
15921ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            that we're "covered" until all the transfers are done.
15922ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            And don't mess with its alignment. */
15923ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp newSP = newTemp(Ity_I32);
15924ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign(newSP, binop(Iop_Add32, mkexpr(oldSP),
15925ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                        mkU32(4 * (nRegs + bitR))));
15926ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15927ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Now the transfers, not including PC */
15928ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         nRegs = 0;
15929ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         for (i = 0; i < 8; i++) {
15930ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if ((regList & (1 << i)) != 0) {
15931ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               putIRegT(i, loadLE( Ity_I32,
15932ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                   binop(Iop_Add32, mkexpr(base),
15933ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                                    mkU32(4 * nRegs))),
15934ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           IRTemp_INVALID );
15935ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               nRegs++;
15936ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
15937ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
15938ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15939ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp newPC = IRTemp_INVALID;
15940ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (bitR) {
15941ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            newPC = newTemp(Ity_I32);
15942ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            assign( newPC, loadLE( Ity_I32,
15943ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                   binop(Iop_Add32, mkexpr(base),
15944ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                                    mkU32(4 * nRegs))));
15945ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
15946ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15947ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Now we can safely install the new SP value */
15948ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putIRegT(13, mkexpr(newSP), IRTemp_INVALID);
15949ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15950ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Reinstate the ITSTATE update. */
15951ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         put_ITSTATE(new_itstate);
15952ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15953ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* now, do we also have to do a branch?  If so, it turns out
15954ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            that the new PC value is encoded exactly as we need it to
15955ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            be -- with CPSR.T in the bottom bit.  So we can simply use
15956ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            it as is, no need to mess with it.  Note, therefore, this
15957ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            is an interworking return. */
15958ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (bitR) {
15959663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            llPutIReg(15, mkexpr(newPC));
15960663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            dres.jk_StopHere = Ijk_Ret;
15961663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            dres.whatNext    = Dis_StopHere;
15962ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
15963ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15964ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("pop {%s0x%04x}\n", bitR ? "pc," : "", regList & 0xFF);
15965ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto decode_success;
15966ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
15967ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
15968ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
15969ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15970ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case BITS7(0,0,0,1,1,1,0):   /* ADDS */
15971ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case BITS7(0,0,0,1,1,1,1): { /* SUBS */
15972ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* ---------------- ADDS Rd, Rn, #uimm3 ---------------- */
15973ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* ---------------- SUBS Rd, Rn, #uimm3 ---------------- */
15974ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt   uimm3 = INSN0(8,6);
15975ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt   rN    = INSN0(5,3);
15976ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt   rD    = INSN0(2,0);
15977ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt   isSub = INSN0(9,9);
15978ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp argL  = newTemp(Ity_I32);
15979ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp argR  = newTemp(Ity_I32);
15980ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( argL, getIRegT(rN) );
15981ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( argR, mkU32(uimm3) );
15982ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putIRegT(rD, binop(isSub ? Iop_Sub32 : Iop_Add32,
15983ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         mkexpr(argL), mkexpr(argR)),
15984ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   condT);
15985ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      setFlags_D1_D2( isSub ? ARMG_CC_OP_SUB : ARMG_CC_OP_ADD,
15986ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      argL, argR, cond_AND_notInIT_T );
15987ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("%s r%u, r%u, #%u\n", isSub ? "subs" : "adds", rD, rN, uimm3);
15988ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      goto decode_success;
15989ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
15990ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15991ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case BITS7(0,0,0,1,1,0,0):   /* ADDS */
15992ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case BITS7(0,0,0,1,1,0,1): { /* SUBS */
15993ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* ---------------- ADDS Rd, Rn, Rm ---------------- */
15994ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* ---------------- SUBS Rd, Rn, Rm ---------------- */
15995ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt   rM    = INSN0(8,6);
15996ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt   rN    = INSN0(5,3);
15997ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt   rD    = INSN0(2,0);
15998ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt   isSub = INSN0(9,9);
15999ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp argL  = newTemp(Ity_I32);
16000ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp argR  = newTemp(Ity_I32);
16001ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( argL, getIRegT(rN) );
16002ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( argR, getIRegT(rM) );
16003ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putIRegT( rD, binop(isSub ? Iop_Sub32 : Iop_Add32,
16004ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          mkexpr(argL), mkexpr(argR)),
16005ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    condT );
16006ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      setFlags_D1_D2( isSub ? ARMG_CC_OP_SUB : ARMG_CC_OP_ADD,
16007ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      argL, argR, cond_AND_notInIT_T );
16008ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("%s r%u, r%u, r%u\n", isSub ? "subs" : "adds", rD, rN, rM);
16009ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      goto decode_success;
16010ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
16011ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16012ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case BITS7(0,1,0,1,0,0,0):   /* STR */
16013ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case BITS7(0,1,0,1,1,0,0): { /* LDR */
16014ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* ------------- LDR Rd, [Rn, Rm] ------------- */
16015ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* ------------- STR Rd, [Rn, Rm] ------------- */
16016ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* LDR/STR Rd, [Rn + Rm] */
16017ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt    rD   = INSN0(2,0);
16018ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt    rN   = INSN0(5,3);
16019ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt    rM   = INSN0(8,6);
16020ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt    isLD = INSN0(11,11);
16021ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16022ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      mk_skip_over_T16_if_cond_is_false(condT);
16023ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      condT = IRTemp_INVALID;
16024ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // now uncond
16025ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16026ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRExpr* ea = binop(Iop_Add32, getIRegT(rN), getIRegT(rM));
16027ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      put_ITSTATE(old_itstate); // backout
16028ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (isLD) {
16029ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putIRegT(rD, loadLE(Ity_I32, ea), IRTemp_INVALID);
16030ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else {
16031ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         storeLE(ea, getIRegT(rD));
16032ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
16033ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      put_ITSTATE(new_itstate); // restore
16034ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16035ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("%s r%u, [r%u, r%u]\n", isLD ? "ldr" : "str", rD, rN, rM);
16036ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      goto decode_success;
16037ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
16038ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16039ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case BITS7(0,1,0,1,0,0,1):
16040ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case BITS7(0,1,0,1,1,0,1): {
16041ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* ------------- LDRH Rd, [Rn, Rm] ------------- */
16042ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* ------------- STRH Rd, [Rn, Rm] ------------- */
16043ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* LDRH/STRH Rd, [Rn + Rm] */
16044ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt    rD   = INSN0(2,0);
16045ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt    rN   = INSN0(5,3);
16046ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt    rM   = INSN0(8,6);
16047ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt    isLD = INSN0(11,11);
16048ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16049ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      mk_skip_over_T16_if_cond_is_false(condT);
16050ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      condT = IRTemp_INVALID;
16051ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // now uncond
16052ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16053ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRExpr* ea = binop(Iop_Add32, getIRegT(rN), getIRegT(rM));
16054ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      put_ITSTATE(old_itstate); // backout
16055ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (isLD) {
16056ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putIRegT(rD, unop(Iop_16Uto32, loadLE(Ity_I16, ea)),
16057ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      IRTemp_INVALID);
16058ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else {
16059ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         storeLE( ea, unop(Iop_32to16, getIRegT(rD)) );
16060ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
16061ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      put_ITSTATE(new_itstate); // restore
16062ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16063ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("%sh r%u, [r%u, r%u]\n", isLD ? "ldr" : "str", rD, rN, rM);
16064ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      goto decode_success;
16065ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
16066ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16067ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case BITS7(0,1,0,1,1,1,1): {
16068ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* ------------- LDRSH Rd, [Rn, Rm] ------------- */
16069ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* LDRSH Rd, [Rn + Rm] */
16070ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt    rD = INSN0(2,0);
16071ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt    rN = INSN0(5,3);
16072ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt    rM = INSN0(8,6);
16073ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16074ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      mk_skip_over_T16_if_cond_is_false(condT);
16075ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      condT = IRTemp_INVALID;
16076ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // now uncond
16077ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16078ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRExpr* ea = binop(Iop_Add32, getIRegT(rN), getIRegT(rM));
16079ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      put_ITSTATE(old_itstate); // backout
16080ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putIRegT(rD, unop(Iop_16Sto32, loadLE(Ity_I16, ea)),
16081ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   IRTemp_INVALID);
16082ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      put_ITSTATE(new_itstate); // restore
16083ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16084ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("ldrsh r%u, [r%u, r%u]\n", rD, rN, rM);
16085ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      goto decode_success;
16086ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
16087ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16088ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case BITS7(0,1,0,1,0,1,1): {
16089ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* ------------- LDRSB Rd, [Rn, Rm] ------------- */
16090ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* LDRSB Rd, [Rn + Rm] */
16091ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt    rD = INSN0(2,0);
16092ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt    rN = INSN0(5,3);
16093ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt    rM = INSN0(8,6);
16094ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16095ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      mk_skip_over_T16_if_cond_is_false(condT);
16096ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      condT = IRTemp_INVALID;
16097ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // now uncond
16098ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16099ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRExpr* ea = binop(Iop_Add32, getIRegT(rN), getIRegT(rM));
16100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      put_ITSTATE(old_itstate); // backout
16101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putIRegT(rD, unop(Iop_8Sto32, loadLE(Ity_I8, ea)),
16102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   IRTemp_INVALID);
16103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      put_ITSTATE(new_itstate); // restore
16104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("ldrsb r%u, [r%u, r%u]\n", rD, rN, rM);
16106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      goto decode_success;
16107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
16108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case BITS7(0,1,0,1,0,1,0):
16110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case BITS7(0,1,0,1,1,1,0): {
16111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* ------------- LDRB Rd, [Rn, Rm] ------------- */
16112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* ------------- STRB Rd, [Rn, Rm] ------------- */
16113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* LDRB/STRB Rd, [Rn + Rm] */
16114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt    rD   = INSN0(2,0);
16115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt    rN   = INSN0(5,3);
16116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt    rM   = INSN0(8,6);
16117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt    isLD = INSN0(11,11);
16118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      mk_skip_over_T16_if_cond_is_false(condT);
16120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      condT = IRTemp_INVALID;
16121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // now uncond
16122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRExpr* ea = binop(Iop_Add32, getIRegT(rN), getIRegT(rM));
16124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      put_ITSTATE(old_itstate); // backout
16125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (isLD) {
16126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putIRegT(rD, unop(Iop_8Uto32, loadLE(Ity_I8, ea)),
16127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  IRTemp_INVALID);
16128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else {
16129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         storeLE( ea, unop(Iop_32to8, getIRegT(rD)) );
16130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
16131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      put_ITSTATE(new_itstate); // restore
16132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("%sb r%u, [r%u, r%u]\n", isLD ? "ldr" : "str", rD, rN, rM);
16134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      goto decode_success;
16135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
16136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   default:
16138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break; /* examine the next shortest prefix */
16139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
16141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* ================ 16-bit 15:11 cases ================ */
16144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (INSN0(15,11)) {
16146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case BITS5(0,0,1,1,0):
16148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case BITS5(0,0,1,1,1): {
16149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* ---------------- ADDS Rn, #uimm8 ---------------- */
16150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* ---------------- SUBS Rn, #uimm8 ---------------- */
16151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt   isSub = INSN0(11,11);
16152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt   rN    = INSN0(10,8);
16153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt   uimm8 = INSN0(7,0);
16154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp argL  = newTemp(Ity_I32);
16155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp argR  = newTemp(Ity_I32);
16156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( argL, getIRegT(rN) );
16157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( argR, mkU32(uimm8) );
16158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putIRegT( rN, binop(isSub ? Iop_Sub32 : Iop_Add32,
16159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          mkexpr(argL), mkexpr(argR)), condT );
16160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      setFlags_D1_D2( isSub ? ARMG_CC_OP_SUB : ARMG_CC_OP_ADD,
16161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      argL, argR, cond_AND_notInIT_T );
16162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("%s r%u, #%u\n", isSub ? "subs" : "adds", rN, uimm8);
16163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      goto decode_success;
16164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
16165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case BITS5(1,0,1,0,0): {
16167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* ---------------- ADD rD, PC, #imm8 * 4 ---------------- */
16168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* a.k.a. ADR */
16169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* rD = align4(PC) + imm8 * 4 */
16170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt rD   = INSN0(10,8);
16171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt imm8 = INSN0(7,0);
16172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putIRegT(rD, binop(Iop_Add32,
16173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         binop(Iop_And32, getIRegT(15), mkU32(~3U)),
16174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         mkU32(imm8 * 4)),
16175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   condT);
16176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("add r%u, pc, #%u\n", rD, imm8 * 4);
16177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      goto decode_success;
16178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
16179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case BITS5(1,0,1,0,1): {
16181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* ---------------- ADD rD, SP, #imm8 * 4 ---------------- */
16182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt rD   = INSN0(10,8);
16183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt imm8 = INSN0(7,0);
16184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putIRegT(rD, binop(Iop_Add32, getIRegT(13), mkU32(imm8 * 4)),
16185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   condT);
16186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("add r%u, r13, #%u\n", rD, imm8 * 4);
16187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      goto decode_success;
16188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
16189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case BITS5(0,0,1,0,1): {
16191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* ---------------- CMP Rn, #uimm8 ---------------- */
16192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt   rN    = INSN0(10,8);
16193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt   uimm8 = INSN0(7,0);
16194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp argL  = newTemp(Ity_I32);
16195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp argR  = newTemp(Ity_I32);
16196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( argL, getIRegT(rN) );
16197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( argR, mkU32(uimm8) );
16198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Update flags regardless of whether in an IT block or not. */
16199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      setFlags_D1_D2( ARMG_CC_OP_SUB, argL, argR, condT );
16200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("cmp r%u, #%u\n", rN, uimm8);
16201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      goto decode_success;
16202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
16203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case BITS5(0,0,1,0,0): {
16205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* -------------- (T1) MOVS Rn, #uimm8 -------------- */
16206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt   rD    = INSN0(10,8);
16207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt   uimm8 = INSN0(7,0);
16208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp oldV  = newTemp(Ity_I32);
16209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp oldC  = newTemp(Ity_I32);
16210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp res   = newTemp(Ity_I32);
16211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( oldV, mk_armg_calculate_flag_v() );
16212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( oldC, mk_armg_calculate_flag_c() );
16213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( res, mkU32(uimm8) );
16214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putIRegT(rD, mkexpr(res), condT);
16215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      setFlags_D1_D2_ND( ARMG_CC_OP_LOGIC, res, oldC, oldV,
16216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         cond_AND_notInIT_T );
16217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("movs r%u, #%u\n", rD, uimm8);
16218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      goto decode_success;
16219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
16220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case BITS5(0,1,0,0,1): {
16222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* ------------- LDR Rd, [PC, #imm8 * 4] ------------- */
16223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* LDR Rd, [align4(PC) + imm8 * 4] */
16224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt   rD   = INSN0(10,8);
16225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt   imm8 = INSN0(7,0);
16226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp ea   = newTemp(Ity_I32);
16227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      mk_skip_over_T16_if_cond_is_false(condT);
16229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      condT = IRTemp_INVALID;
16230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // now uncond
16231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign(ea, binop(Iop_Add32,
16233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       binop(Iop_And32, getIRegT(15), mkU32(~3U)),
16234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       mkU32(imm8 * 4)));
16235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      put_ITSTATE(old_itstate); // backout
16236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putIRegT(rD, loadLE(Ity_I32, mkexpr(ea)),
16237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   IRTemp_INVALID);
16238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      put_ITSTATE(new_itstate); // restore
16239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("ldr r%u, [pc, #%u]\n", rD, imm8 * 4);
16241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      goto decode_success;
16242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
16243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case BITS5(0,1,1,0,0):   /* STR */
16245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case BITS5(0,1,1,0,1): { /* LDR */
16246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* ------------- LDR Rd, [Rn, #imm5 * 4] ------------- */
16247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* ------------- STR Rd, [Rn, #imm5 * 4] ------------- */
16248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* LDR/STR Rd, [Rn + imm5 * 4] */
16249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt    rD   = INSN0(2,0);
16250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt    rN   = INSN0(5,3);
16251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt    imm5 = INSN0(10,6);
16252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt    isLD = INSN0(11,11);
16253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      mk_skip_over_T16_if_cond_is_false(condT);
16255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      condT = IRTemp_INVALID;
16256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // now uncond
16257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRExpr* ea = binop(Iop_Add32, getIRegT(rN), mkU32(imm5 * 4));
16259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      put_ITSTATE(old_itstate); // backout
16260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (isLD) {
16261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putIRegT(rD, loadLE(Ity_I32, ea), IRTemp_INVALID);
16262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else {
16263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         storeLE( ea, getIRegT(rD) );
16264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
16265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      put_ITSTATE(new_itstate); // restore
16266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("%s r%u, [r%u, #%u]\n", isLD ? "ldr" : "str", rD, rN, imm5 * 4);
16268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      goto decode_success;
16269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
16270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case BITS5(1,0,0,0,0):   /* STRH */
16272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case BITS5(1,0,0,0,1): { /* LDRH */
16273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* ------------- LDRH Rd, [Rn, #imm5 * 2] ------------- */
16274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* ------------- STRH Rd, [Rn, #imm5 * 2] ------------- */
16275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* LDRH/STRH Rd, [Rn + imm5 * 2] */
16276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt    rD   = INSN0(2,0);
16277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt    rN   = INSN0(5,3);
16278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt    imm5 = INSN0(10,6);
16279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt    isLD = INSN0(11,11);
16280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      mk_skip_over_T16_if_cond_is_false(condT);
16282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      condT = IRTemp_INVALID;
16283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // now uncond
16284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRExpr* ea = binop(Iop_Add32, getIRegT(rN), mkU32(imm5 * 2));
16286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      put_ITSTATE(old_itstate); // backout
16287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (isLD) {
16288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putIRegT(rD, unop(Iop_16Uto32, loadLE(Ity_I16, ea)),
16289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  IRTemp_INVALID);
16290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else {
16291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         storeLE( ea, unop(Iop_32to16, getIRegT(rD)) );
16292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
16293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      put_ITSTATE(new_itstate); // restore
16294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("%sh r%u, [r%u, #%u]\n", isLD ? "ldr" : "str", rD, rN, imm5 * 2);
16296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      goto decode_success;
16297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
16298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case BITS5(0,1,1,1,0):   /* STRB */
16300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case BITS5(0,1,1,1,1): { /* LDRB */
16301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* ------------- LDRB Rd, [Rn, #imm5] ------------- */
16302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* ------------- STRB Rd, [Rn, #imm5] ------------- */
16303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* LDRB/STRB Rd, [Rn + imm5] */
16304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt    rD   = INSN0(2,0);
16305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt    rN   = INSN0(5,3);
16306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt    imm5 = INSN0(10,6);
16307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt    isLD = INSN0(11,11);
16308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      mk_skip_over_T16_if_cond_is_false(condT);
16310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      condT = IRTemp_INVALID;
16311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // now uncond
16312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRExpr* ea = binop(Iop_Add32, getIRegT(rN), mkU32(imm5));
16314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      put_ITSTATE(old_itstate); // backout
16315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (isLD) {
16316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putIRegT(rD, unop(Iop_8Uto32, loadLE(Ity_I8, ea)),
16317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  IRTemp_INVALID);
16318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else {
16319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         storeLE( ea, unop(Iop_32to8, getIRegT(rD)) );
16320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
16321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      put_ITSTATE(new_itstate); // restore
16322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("%sb r%u, [r%u, #%u]\n", isLD ? "ldr" : "str", rD, rN, imm5);
16324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      goto decode_success;
16325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
16326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case BITS5(1,0,0,1,0):   /* STR */
16328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case BITS5(1,0,0,1,1): { /* LDR */
16329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* ------------- LDR Rd, [SP, #imm8 * 4] ------------- */
16330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* ------------- STR Rd, [SP, #imm8 * 4] ------------- */
16331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* LDR/STR Rd, [SP + imm8 * 4] */
16332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt rD    = INSN0(10,8);
16333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt imm8  = INSN0(7,0);
16334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt isLD  = INSN0(11,11);
16335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      mk_skip_over_T16_if_cond_is_false(condT);
16337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      condT = IRTemp_INVALID;
16338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // now uncond
16339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRExpr* ea = binop(Iop_Add32, getIRegT(13), mkU32(imm8 * 4));
16341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      put_ITSTATE(old_itstate); // backout
16342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (isLD) {
16343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putIRegT(rD, loadLE(Ity_I32, ea), IRTemp_INVALID);
16344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else {
16345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         storeLE(ea, getIRegT(rD));
16346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
16347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      put_ITSTATE(new_itstate); // restore
16348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("%s r%u, [sp, #%u]\n", isLD ? "ldr" : "str", rD, imm8 * 4);
16350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      goto decode_success;
16351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
16352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case BITS5(1,1,0,0,1): {
16354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* ------------- LDMIA Rn!, {reglist} ------------- */
16355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Int i, nRegs = 0;
16356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt rN   = INSN0(10,8);
16357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt list = INSN0(7,0);
16358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Empty lists aren't allowed. */
16359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (list != 0) {
16360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         mk_skip_over_T16_if_cond_is_false(condT);
16361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         condT = IRTemp_INVALID;
16362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         put_ITSTATE(old_itstate);
16363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         // now uncond
16364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp oldRn = newTemp(Ity_I32);
16366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp base  = newTemp(Ity_I32);
16367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign(oldRn, getIRegT(rN));
16368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign(base, binop(Iop_And32, mkexpr(oldRn), mkU32(~3U)));
16369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         for (i = 0; i < 8; i++) {
16370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (0 == (list & (1 << i)))
16371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               continue;
16372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            nRegs++;
16373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            putIRegT(
16374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               i, loadLE(Ity_I32,
16375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         binop(Iop_Add32, mkexpr(base),
16376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                          mkU32(nRegs * 4 - 4))),
16377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               IRTemp_INVALID
16378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            );
16379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
16380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Only do the writeback for rN if it isn't in the list of
16381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            registers to be transferred. */
16382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (0 == (list & (1 << rN))) {
16383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            putIRegT(rN,
16384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     binop(Iop_Add32, mkexpr(oldRn),
16385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                      mkU32(nRegs * 4)),
16386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     IRTemp_INVALID
16387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            );
16388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
16389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Reinstate the ITSTATE update. */
16391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         put_ITSTATE(new_itstate);
16392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("ldmia r%u!, {0x%04x}\n", rN, list);
16394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto decode_success;
16395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
16396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
16397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
16398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case BITS5(1,1,0,0,0): {
16400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* ------------- STMIA Rn!, {reglist} ------------- */
16401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Int i, nRegs = 0;
16402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt rN   = INSN0(10,8);
16403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt list = INSN0(7,0);
16404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Empty lists aren't allowed.  Also, if rN is in the list then
16405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         it must be the lowest numbered register in the list. */
16406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Bool valid = list != 0;
16407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (valid && 0 != (list & (1 << rN))) {
16408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         for (i = 0; i < rN; i++) {
16409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (0 != (list & (1 << i)))
16410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               valid = False;
16411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
16412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
16413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (valid) {
16414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         mk_skip_over_T16_if_cond_is_false(condT);
16415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         condT = IRTemp_INVALID;
16416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         put_ITSTATE(old_itstate);
16417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         // now uncond
16418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp oldRn = newTemp(Ity_I32);
16420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp base = newTemp(Ity_I32);
16421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign(oldRn, getIRegT(rN));
16422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign(base, binop(Iop_And32, mkexpr(oldRn), mkU32(~3U)));
16423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         for (i = 0; i < 8; i++) {
16424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (0 == (list & (1 << i)))
16425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               continue;
16426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            nRegs++;
16427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            storeLE( binop(Iop_Add32, mkexpr(base), mkU32(nRegs * 4 - 4)),
16428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     getIRegT(i) );
16429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
16430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Always do the writeback. */
16431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putIRegT(rN,
16432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  binop(Iop_Add32, mkexpr(oldRn),
16433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                   mkU32(nRegs * 4)),
16434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  IRTemp_INVALID);
16435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Reinstate the ITSTATE update. */
16437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         put_ITSTATE(new_itstate);
16438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("stmia r%u!, {0x%04x}\n", rN, list);
16440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto decode_success;
16441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
16442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
16443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
16444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case BITS5(0,0,0,0,0):   /* LSLS */
16446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case BITS5(0,0,0,0,1):   /* LSRS */
16447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case BITS5(0,0,0,1,0): { /* ASRS */
16448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* ---------------- LSLS Rd, Rm, #imm5 ---------------- */
16449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* ---------------- LSRS Rd, Rm, #imm5 ---------------- */
16450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* ---------------- ASRS Rd, Rm, #imm5 ---------------- */
16451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt   rD   = INSN0(2,0);
16452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt   rM   = INSN0(5,3);
16453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt   imm5 = INSN0(10,6);
16454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp res  = newTemp(Ity_I32);
16455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp resC = newTemp(Ity_I32);
16456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp rMt  = newTemp(Ity_I32);
16457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp oldV = newTemp(Ity_I32);
16458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HChar* wot  = "???";
16459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign(rMt, getIRegT(rM));
16460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign(oldV, mk_armg_calculate_flag_v());
16461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Looks like INSN0(12,11) are the standard 'how' encoding.
16462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         Could compactify if the ROR case later appears. */
16463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch (INSN0(15,11)) {
16464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case BITS5(0,0,0,0,0):
16465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            compute_result_and_C_after_LSL_by_imm5(
16466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               dis_buf, &res, &resC, rMt, imm5, rM
16467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            );
16468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            wot = "lsl";
16469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
16470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case BITS5(0,0,0,0,1):
16471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            compute_result_and_C_after_LSR_by_imm5(
16472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               dis_buf, &res, &resC, rMt, imm5, rM
16473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            );
16474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            wot = "lsr";
16475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
16476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case BITS5(0,0,0,1,0):
16477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            compute_result_and_C_after_ASR_by_imm5(
16478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               dis_buf, &res, &resC, rMt, imm5, rM
16479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            );
16480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            wot = "asr";
16481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
16482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         default:
16483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /*NOTREACHED*/vassert(0);
16484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
16485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // not safe to read guest state after this point
16486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putIRegT(rD, mkexpr(res), condT);
16487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      setFlags_D1_D2_ND( ARMG_CC_OP_LOGIC, res, resC, oldV,
16488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         cond_AND_notInIT_T );
16489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* ignore buf and roll our own output */
16490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("%ss r%u, r%u, #%u\n", wot, rD, rM, imm5);
16491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      goto decode_success;
16492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
16493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case BITS5(1,1,1,0,0): {
16495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* ---------------- B #simm11 ---------------- */
16496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Int  simm11 = INSN0(10,0);
16497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           simm11 = (simm11 << 21) >> 20;
16498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt dst    = simm11 + guest_R15_curr_instr_notENC + 4;
16499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Only allowed outside or last-in IT block; SIGILL if not so. */
16500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      gen_SIGILL_T_if_in_but_NLI_ITBlock(old_itstate, new_itstate);
16501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // and skip this insn if not selected; being cleverer is too
16502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // difficult
16503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      mk_skip_over_T16_if_cond_is_false(condT);
16504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      condT = IRTemp_INVALID;
16505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // now uncond
16506663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      llPutIReg(15, mkU32( dst | 1 /*CPSR.T*/ ));
16507663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      dres.jk_StopHere = Ijk_Boring;
16508663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      dres.whatNext    = Dis_StopHere;
16509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("b 0x%x\n", dst);
16510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      goto decode_success;
16511ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
16512ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16513ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   default:
16514ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break; /* examine the next shortest prefix */
16515ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16516ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
16517ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* ================ 16-bit 15:12 cases ================ */
16520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16521ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (INSN0(15,12)) {
16522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16523ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case BITS4(1,1,0,1): {
16524ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* ---------------- Bcond #simm8 ---------------- */
16525ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt cond  = INSN0(11,8);
16526ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Int  simm8 = INSN0(7,0);
16527ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           simm8 = (simm8 << 24) >> 23;
16528ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt dst   = simm8 + guest_R15_curr_instr_notENC + 4;
16529ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (cond != ARMCondAL && cond != ARMCondNV) {
16530ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Not allowed in an IT block; SIGILL if so. */
16531ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         gen_SIGILL_T_if_in_ITBlock(old_itstate, new_itstate);
16532ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16533ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp kondT = newTemp(Ity_I32);
16534ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( kondT, mk_armg_calculate_condition(cond) );
16535ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         stmt( IRStmt_Exit( unop(Iop_32to1, mkexpr(kondT)),
16536ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            Ijk_Boring,
16537663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                            IRConst_U32(dst | 1/*CPSR.T*/),
16538663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                            OFFB_R15T ));
16539663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         llPutIReg(15, mkU32( (guest_R15_curr_instr_notENC + 2)
16540663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                              | 1 /*CPSR.T*/ ));
16541663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         dres.jk_StopHere = Ijk_Boring;
16542663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         dres.whatNext    = Dis_StopHere;
16543ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("b%s 0x%x\n", nCC(cond), dst);
16544ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto decode_success;
16545ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
16546ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
16547ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
16548ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16549ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   default:
16550ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break; /* hmm, nothing matched */
16551ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16552ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
16553ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16554ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* ================ 16-bit misc cases ================ */
16555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* ------ NOP ------ */
16557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (INSN0(15,0) == 0xBF00) {
16558ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("nop");
16559ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      goto decode_success;
16560ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
16561ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* ----------------------------------------------------------- */
16563ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* --                                                       -- */
16564ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* -- Thumb 32-bit integer instructions                     -- */
16565ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* --                                                       -- */
16566ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* ----------------------------------------------------------- */
16567ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16568ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  define INSN1(_bMax,_bMin)  SLICE_UInt(((UInt)insn1), (_bMax), (_bMin))
16569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16570ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* second 16 bits of the instruction, if any */
16571663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vassert(insn1 == 0);
16572663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   insn1 = getUShortLittleEndianly( guest_instr+2 );
16573ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16574ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   anOp   = Iop_INVALID; /* paranoia */
16575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   anOpNm = NULL;        /* paranoia */
16576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Change result defaults to suit 32-bit insns. */
16578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(dres.whatNext   == Dis_Continue);
16579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(dres.len        == 2);
16580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(dres.continueAt == 0);
16581ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   dres.len = 4;
16582ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* ---------------- BL/BLX simm26 ---------------- */
16584ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (BITS5(1,1,1,1,0) == INSN0(15,11) && BITS2(1,1) == INSN1(15,14)) {
16585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt isBL = INSN1(12,12);
16586ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt bS   = INSN0(10,10);
16587ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt bJ1  = INSN1(13,13);
16588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt bJ2  = INSN1(11,11);
16589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt bI1  = 1 ^ (bJ1 ^ bS);
16590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt bI2  = 1 ^ (bJ2 ^ bS);
16591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Int simm25
16592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         =   (bS          << (1 + 1 + 10 + 11 + 1))
16593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           | (bI1         << (1 + 10 + 11 + 1))
16594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           | (bI2         << (10 + 11 + 1))
16595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           | (INSN0(9,0)  << (11 + 1))
16596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           | (INSN1(10,0) << 1);
16597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      simm25 = (simm25 << 7) >> 7;
16598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert(0 == (guest_R15_curr_instr_notENC & 1));
16600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt dst = simm25 + guest_R15_curr_instr_notENC + 4;
16601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16602ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* One further validity case to check: in the case of BLX
16603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         (not-BL), that insn1[0] must be zero. */
16604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Bool valid = True;
16605ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (isBL == 0 && INSN1(0,0) == 1) valid = False;
16606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (valid) {
16607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Only allowed outside or last-in IT block; SIGILL if not so. */
16608ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         gen_SIGILL_T_if_in_but_NLI_ITBlock(old_itstate, new_itstate);
16609ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         // and skip this insn if not selected; being cleverer is too
16610ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         // difficult
16611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         mk_skip_over_T32_if_cond_is_false(condT);
16612ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         condT = IRTemp_INVALID;
16613ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         // now uncond
16614ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16615ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* We're returning to Thumb code, hence "| 1" */
16616ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putIRegT( 14, mkU32( (guest_R15_curr_instr_notENC + 4) | 1 ),
16617ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   IRTemp_INVALID);
16618ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (isBL) {
16619ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* BL: unconditional T -> T call */
16620ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* we're calling Thumb code, hence "| 1" */
16621663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            llPutIReg(15, mkU32( dst | 1 ));
16622ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            DIP("bl 0x%x (stay in Thumb mode)\n", dst);
16623ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
16624ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* BLX: unconditional T -> A call */
16625ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* we're calling ARM code, hence "& 3" to align to a
16626ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               valid ARM insn address */
16627663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            llPutIReg(15, mkU32( dst & ~3 ));
16628ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            DIP("blx 0x%x (switch to ARM mode)\n", dst & ~3);
16629ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
16630663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         dres.whatNext    = Dis_StopHere;
16631663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         dres.jk_StopHere = Ijk_Call;
16632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto decode_success;
16633ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
16634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
16635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* ---------------- {LD,ST}M{IA,DB} ---------------- */
16637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (0x3a2 == INSN0(15,6) // {LD,ST}MIA
16638ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       || 0x3a4 == INSN0(15,6)) { // {LD,ST}MDB
16639ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt bW      = INSN0(5,5); /* writeback Rn ? */
16640ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt bL      = INSN0(4,4);
16641ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt rN      = INSN0(3,0);
16642ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt bP      = INSN1(15,15); /* reglist entry for r15 */
16643ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt bM      = INSN1(14,14); /* reglist entry for r14 */
16644ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt rLmost  = INSN1(12,0);  /* reglist entry for r0 .. 12 */
16645ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt rL13    = INSN1(13,13); /* must be zero */
16646ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt regList = 0;
16647ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Bool valid   = True;
16648ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16649ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt bINC    = 1;
16650ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt bBEFORE = 0;
16651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (INSN0(15,6) == 0x3a4) {
16652ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         bINC    = 0;
16653ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         bBEFORE = 1;
16654ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
16655ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16656ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* detect statically invalid cases, and construct the final
16657ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         reglist */
16658ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (rL13 == 1)
16659ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         valid = False;
16660ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16661ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (bL == 1) {
16662ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         regList = (bP << 15) | (bM << 14) | rLmost;
16663ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (rN == 15)                       valid = False;
16664ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (popcount32(regList) < 2)        valid = False;
16665ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (bP == 1 && bM == 1)             valid = False;
16666ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (bW == 1 && (regList & (1<<rN))) valid = False;
16667ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else {
16668ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         regList = (bM << 14) | rLmost;
16669ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (bP == 1)                        valid = False;
16670ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (rN == 15)                       valid = False;
16671ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (popcount32(regList) < 2)        valid = False;
16672ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (bW == 1 && (regList & (1<<rN))) valid = False;
16673ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
16674ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16675ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (valid) {
16676ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (bL == 1 && bP == 1) {
16677ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            // We'll be writing the PC.  Hence:
16678ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* Only allowed outside or last-in IT block; SIGILL if not so. */
16679ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            gen_SIGILL_T_if_in_but_NLI_ITBlock(old_itstate, new_itstate);
16680ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
16681ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16682ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Go uncond: */
16683ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         mk_skip_over_T32_if_cond_is_false(condT);
16684ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         condT = IRTemp_INVALID;
16685ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         // now uncond
16686ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16687663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         /* Generate the IR.  This might generate a write to R15. */
16688ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         mk_ldm_stm(False/*!arm*/, rN, bINC, bBEFORE, bW, bL, regList);
16689ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16690ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (bL == 1 && (regList & (1<<15))) {
16691ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            // If we wrote to R15, we have an interworking return to
16692ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            // deal with.
16693663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            llPutIReg(15, llGetIReg(15));
16694663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            dres.jk_StopHere = Ijk_Ret;
16695663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            dres.whatNext    = Dis_StopHere;
16696ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
16697ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16698ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("%sm%c%c r%u%s, {0x%04x}\n",
16699ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              bL == 1 ? "ld" : "st", bINC ? 'i' : 'd', bBEFORE ? 'b' : 'a',
16700ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              rN, bW ? "!" : "", regList);
16701ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16702ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto decode_success;
16703ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
16704ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
16705ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16706ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* -------------- (T3) ADD{S}.W Rd, Rn, #constT -------------- */
16707ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (INSN0(15,11) == BITS5(1,1,1,1,0)
16708ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && INSN0(9,5) == BITS5(0,1,0,0,0)
16709ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && INSN1(15,15) == 0) {
16710ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt bS = INSN0(4,4);
16711ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt rN = INSN0(3,0);
16712ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt rD = INSN1(11,8);
16713ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Bool valid = !isBadRegT(rN) && !isBadRegT(rD);
16714663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* but allow "add.w reg, sp, #constT" for reg != PC */
16715663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (!valid && rD <= 14 && rN == 13)
16716ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         valid = True;
16717ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (valid) {
16718ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp argL  = newTemp(Ity_I32);
16719ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp argR  = newTemp(Ity_I32);
16720ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp res   = newTemp(Ity_I32);
16721ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         UInt   imm32 = thumbExpandImm_from_I0_I1(NULL, insn0, insn1);
16722ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign(argL, getIRegT(rN));
16723ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign(argR, mkU32(imm32));
16724ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign(res,  binop(Iop_Add32, mkexpr(argL), mkexpr(argR)));
16725ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putIRegT(rD, mkexpr(res), condT);
16726ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (bS == 1)
16727ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            setFlags_D1_D2( ARMG_CC_OP_ADD, argL, argR, condT );
16728ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("add%s.w r%u, r%u, #%u\n",
16729ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             bS == 1 ? "s" : "", rD, rN, imm32);
16730ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto decode_success;
16731ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
16732ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
16733ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16734b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   /* ---------------- (T4) ADDW Rd, Rn, #uimm12 -------------- */
1673553309af808693e7481777590bf359702e1c05b17Kenny Root   if (INSN0(15,11) == BITS5(1,1,1,1,0)
1673653309af808693e7481777590bf359702e1c05b17Kenny Root       && INSN0(9,4) == BITS6(1,0,0,0,0,0)
1673753309af808693e7481777590bf359702e1c05b17Kenny Root       && INSN1(15,15) == 0) {
1673853309af808693e7481777590bf359702e1c05b17Kenny Root      UInt rN = INSN0(3,0);
1673953309af808693e7481777590bf359702e1c05b17Kenny Root      UInt rD = INSN1(11,8);
1674053309af808693e7481777590bf359702e1c05b17Kenny Root      Bool valid = !isBadRegT(rN) && !isBadRegT(rD);
16741663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* but allow "addw reg, sp, #uimm12" for reg != PC */
16742663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (!valid && rD <= 14 && rN == 13)
1674353309af808693e7481777590bf359702e1c05b17Kenny Root         valid = True;
1674453309af808693e7481777590bf359702e1c05b17Kenny Root      if (valid) {
1674553309af808693e7481777590bf359702e1c05b17Kenny Root         IRTemp argL = newTemp(Ity_I32);
1674653309af808693e7481777590bf359702e1c05b17Kenny Root         IRTemp argR = newTemp(Ity_I32);
1674753309af808693e7481777590bf359702e1c05b17Kenny Root         IRTemp res  = newTemp(Ity_I32);
16748b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         UInt imm12  = (INSN0(10,10) << 11) | (INSN1(14,12) << 8) | INSN1(7,0);
1674953309af808693e7481777590bf359702e1c05b17Kenny Root         assign(argL, getIRegT(rN));
1675053309af808693e7481777590bf359702e1c05b17Kenny Root         assign(argR, mkU32(imm12));
1675153309af808693e7481777590bf359702e1c05b17Kenny Root         assign(res,  binop(Iop_Add32, mkexpr(argL), mkexpr(argR)));
1675253309af808693e7481777590bf359702e1c05b17Kenny Root         putIRegT(rD, mkexpr(res), condT);
1675353309af808693e7481777590bf359702e1c05b17Kenny Root         DIP("addw r%u, r%u, #%u\n", rD, rN, imm12);
1675453309af808693e7481777590bf359702e1c05b17Kenny Root         goto decode_success;
1675553309af808693e7481777590bf359702e1c05b17Kenny Root      }
1675653309af808693e7481777590bf359702e1c05b17Kenny Root   }
1675753309af808693e7481777590bf359702e1c05b17Kenny Root
16758ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* ---------------- (T2) CMP.W Rn, #constT ---------------- */
16759ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* ---------------- (T2) CMN.W Rn, #constT ---------------- */
16760ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (INSN0(15,11) == BITS5(1,1,1,1,0)
16761ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && (   INSN0(9,4) == BITS6(0,1,1,0,1,1)  // CMP
16762ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           || INSN0(9,4) == BITS6(0,1,0,0,0,1)) // CMN
16763ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && INSN1(15,15) == 0
16764ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && INSN1(11,8) == BITS4(1,1,1,1)) {
16765ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt rN = INSN0(3,0);
16766ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (rN != 15) {
16767ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp argL  = newTemp(Ity_I32);
16768ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp argR  = newTemp(Ity_I32);
16769ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         Bool   isCMN = INSN0(9,4) == BITS6(0,1,0,0,0,1);
16770ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         UInt   imm32 = thumbExpandImm_from_I0_I1(NULL, insn0, insn1);
16771ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign(argL, getIRegT(rN));
16772ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign(argR, mkU32(imm32));
16773ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         setFlags_D1_D2( isCMN ? ARMG_CC_OP_ADD : ARMG_CC_OP_SUB,
16774ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         argL, argR, condT );
16775ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("%s.w r%u, #%u\n", isCMN ? "cmn" : "cmp", rN, imm32);
16776ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto decode_success;
16777ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
16778ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
16779ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16780ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* -------------- (T1) TST.W Rn, #constT -------------- */
16781ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* -------------- (T1) TEQ.W Rn, #constT -------------- */
16782ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (INSN0(15,11) == BITS5(1,1,1,1,0)
16783ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && (   INSN0(9,4) == BITS6(0,0,0,0,0,1)  // TST
16784ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           || INSN0(9,4) == BITS6(0,0,1,0,0,1)) // TEQ
16785ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && INSN1(15,15) == 0
16786ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && INSN1(11,8) == BITS4(1,1,1,1)) {
16787ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt rN = INSN0(3,0);
16788ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (!isBadRegT(rN)) { // yes, really, it's inconsistent with CMP.W
16789ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         Bool  isTST  = INSN0(9,4) == BITS6(0,0,0,0,0,1);
16790ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp argL  = newTemp(Ity_I32);
16791ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp argR  = newTemp(Ity_I32);
16792ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp res   = newTemp(Ity_I32);
16793ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp oldV  = newTemp(Ity_I32);
16794ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp oldC  = newTemp(Ity_I32);
16795ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         Bool   updC  = False;
16796ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         UInt   imm32 = thumbExpandImm_from_I0_I1(&updC, insn0, insn1);
16797ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign(argL, getIRegT(rN));
16798ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign(argR, mkU32(imm32));
16799ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign(res,  binop(isTST ? Iop_And32 : Iop_Xor32,
16800ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            mkexpr(argL), mkexpr(argR)));
16801ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( oldV, mk_armg_calculate_flag_v() );
16802ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( oldC, updC
16803ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       ? mkU32((imm32 >> 31) & 1)
16804ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       : mk_armg_calculate_flag_c() );
16805ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         setFlags_D1_D2_ND( ARMG_CC_OP_LOGIC, res, oldC, oldV, condT );
16806ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("%s.w r%u, #%u\n", isTST ? "tst" : "teq", rN, imm32);
16807ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto decode_success;
16808ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
16809ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
16810ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16811ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* -------------- (T3) SUB{S}.W Rd, Rn, #constT -------------- */
16812ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* -------------- (T3) RSB{S}.W Rd, Rn, #constT -------------- */
16813ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (INSN0(15,11) == BITS5(1,1,1,1,0)
16814ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && (INSN0(9,5) == BITS5(0,1,1,0,1) // SUB
16815ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           || INSN0(9,5) == BITS5(0,1,1,1,0)) // RSB
16816ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && INSN1(15,15) == 0) {
16817ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Bool isRSB = INSN0(9,5) == BITS5(0,1,1,1,0);
16818ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt bS    = INSN0(4,4);
16819ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt rN    = INSN0(3,0);
16820ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt rD    = INSN1(11,8);
16821ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Bool valid = !isBadRegT(rN) && !isBadRegT(rD);
16822b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      /* but allow "sub{s}.w reg, sp, #constT
16823b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         this is (T2) of "SUB (SP minus immediate)" */
16824b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      if (!valid && !isRSB && rN == 13 && rD != 15)
16825ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         valid = True;
16826ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (valid) {
16827ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp argL  = newTemp(Ity_I32);
16828ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp argR  = newTemp(Ity_I32);
16829ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp res   = newTemp(Ity_I32);
16830ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         UInt   imm32 = thumbExpandImm_from_I0_I1(NULL, insn0, insn1);
16831ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign(argL, getIRegT(rN));
16832ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign(argR, mkU32(imm32));
16833ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign(res,  isRSB
16834ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      ? binop(Iop_Sub32, mkexpr(argR), mkexpr(argL))
16835ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      : binop(Iop_Sub32, mkexpr(argL), mkexpr(argR)));
16836ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putIRegT(rD, mkexpr(res), condT);
16837ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (bS == 1) {
16838ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (isRSB)
16839ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               setFlags_D1_D2( ARMG_CC_OP_SUB, argR, argL, condT );
16840ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            else
16841ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               setFlags_D1_D2( ARMG_CC_OP_SUB, argL, argR, condT );
16842ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
16843ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("%s%s.w r%u, r%u, #%u\n",
16844ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             isRSB ? "rsb" : "sub", bS == 1 ? "s" : "", rD, rN, imm32);
16845ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto decode_success;
16846ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
16847ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
16848ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16849b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   /* -------------- (T4) SUBW Rd, Rn, #uimm12 ------------------- */
168506116123147b1a0a13a2ead4c0d7374e7af5ce741Kenny Root   if (INSN0(15,11) == BITS5(1,1,1,1,0)
168516116123147b1a0a13a2ead4c0d7374e7af5ce741Kenny Root       && INSN0(9,4) == BITS6(1,0,1,0,1,0)
168526116123147b1a0a13a2ead4c0d7374e7af5ce741Kenny Root       && INSN1(15,15) == 0) {
168536116123147b1a0a13a2ead4c0d7374e7af5ce741Kenny Root      UInt rN = INSN0(3,0);
168546116123147b1a0a13a2ead4c0d7374e7af5ce741Kenny Root      UInt rD = INSN1(11,8);
168556116123147b1a0a13a2ead4c0d7374e7af5ce741Kenny Root      Bool valid = !isBadRegT(rN) && !isBadRegT(rD);
16856b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      /* but allow "subw sp, sp, #uimm12" */
16857b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      if (!valid && rD == 13 && rN == 13)
168586116123147b1a0a13a2ead4c0d7374e7af5ce741Kenny Root         valid = True;
168596116123147b1a0a13a2ead4c0d7374e7af5ce741Kenny Root      if (valid) {
168606116123147b1a0a13a2ead4c0d7374e7af5ce741Kenny Root         IRTemp argL  = newTemp(Ity_I32);
168616116123147b1a0a13a2ead4c0d7374e7af5ce741Kenny Root         IRTemp argR  = newTemp(Ity_I32);
168626116123147b1a0a13a2ead4c0d7374e7af5ce741Kenny Root         IRTemp res   = newTemp(Ity_I32);
168636116123147b1a0a13a2ead4c0d7374e7af5ce741Kenny Root         UInt imm12   = (INSN0(10,10) << 11) | (INSN1(14,12) << 8) | INSN1(7,0);
168646116123147b1a0a13a2ead4c0d7374e7af5ce741Kenny Root         assign(argL, getIRegT(rN));
168656116123147b1a0a13a2ead4c0d7374e7af5ce741Kenny Root         assign(argR, mkU32(imm12));
168666116123147b1a0a13a2ead4c0d7374e7af5ce741Kenny Root         assign(res,  binop(Iop_Sub32, mkexpr(argL), mkexpr(argR)));
168676116123147b1a0a13a2ead4c0d7374e7af5ce741Kenny Root         putIRegT(rD, mkexpr(res), condT);
168686116123147b1a0a13a2ead4c0d7374e7af5ce741Kenny Root         DIP("subw r%u, r%u, #%u\n", rD, rN, imm12);
168696116123147b1a0a13a2ead4c0d7374e7af5ce741Kenny Root         goto decode_success;
168706116123147b1a0a13a2ead4c0d7374e7af5ce741Kenny Root      }
168716116123147b1a0a13a2ead4c0d7374e7af5ce741Kenny Root   }
168726116123147b1a0a13a2ead4c0d7374e7af5ce741Kenny Root
16873ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* -------------- (T1) ADC{S}.W Rd, Rn, #constT -------------- */
16874ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* -------------- (T1) SBC{S}.W Rd, Rn, #constT -------------- */
16875ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (INSN0(15,11) == BITS5(1,1,1,1,0)
16876ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && (   INSN0(9,5) == BITS5(0,1,0,1,0)  // ADC
16877ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           || INSN0(9,5) == BITS5(0,1,0,1,1)) // SBC
16878ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && INSN1(15,15) == 0) {
16879ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* ADC:  Rd = Rn + constT + oldC */
16880ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* SBC:  Rd = Rn - constT - (oldC ^ 1) */
16881ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt bS    = INSN0(4,4);
16882ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt rN    = INSN0(3,0);
16883ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt rD    = INSN1(11,8);
16884ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (!isBadRegT(rN) && !isBadRegT(rD)) {
16885ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp argL  = newTemp(Ity_I32);
16886ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp argR  = newTemp(Ity_I32);
16887ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp res   = newTemp(Ity_I32);
16888ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp oldC  = newTemp(Ity_I32);
16889ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         UInt   imm32 = thumbExpandImm_from_I0_I1(NULL, insn0, insn1);
16890ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign(argL, getIRegT(rN));
16891ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign(argR, mkU32(imm32));
16892ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign(oldC, mk_armg_calculate_flag_c() );
16893ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HChar* nm  = "???";
16894ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         switch (INSN0(9,5)) {
16895ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case BITS5(0,1,0,1,0): // ADC
16896ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               nm = "adc";
16897ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               assign(res,
16898ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      binop(Iop_Add32,
16899ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            binop(Iop_Add32, mkexpr(argL), mkexpr(argR)),
16900ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            mkexpr(oldC) ));
16901ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               putIRegT(rD, mkexpr(res), condT);
16902ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               if (bS)
16903ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  setFlags_D1_D2_ND( ARMG_CC_OP_ADC,
16904ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                     argL, argR, oldC, condT );
16905ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
16906ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case BITS5(0,1,0,1,1): // SBC
16907ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               nm = "sbc";
16908ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               assign(res,
16909ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      binop(Iop_Sub32,
16910ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            binop(Iop_Sub32, mkexpr(argL), mkexpr(argR)),
16911ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            binop(Iop_Xor32, mkexpr(oldC), mkU32(1)) ));
16912ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               putIRegT(rD, mkexpr(res), condT);
16913ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               if (bS)
16914ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  setFlags_D1_D2_ND( ARMG_CC_OP_SBB,
16915ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                     argL, argR, oldC, condT );
16916ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
16917ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            default:
16918ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              vassert(0);
16919ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
16920ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("%s%s.w r%u, r%u, #%u\n",
16921ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             nm, bS == 1 ? "s" : "", rD, rN, imm32);
16922ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto decode_success;
16923ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
16924ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
16925ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16926ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* -------------- (T1) ORR{S}.W Rd, Rn, #constT -------------- */
16927ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* -------------- (T1) AND{S}.W Rd, Rn, #constT -------------- */
16928ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* -------------- (T1) BIC{S}.W Rd, Rn, #constT -------------- */
16929ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* -------------- (T1) EOR{S}.W Rd, Rn, #constT -------------- */
16930ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (INSN0(15,11) == BITS5(1,1,1,1,0)
16931ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && (   INSN0(9,5) == BITS5(0,0,0,1,0)  // ORR
16932ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           || INSN0(9,5) == BITS5(0,0,0,0,0)  // AND
16933ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           || INSN0(9,5) == BITS5(0,0,0,0,1)  // BIC
16934ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           || INSN0(9,5) == BITS5(0,0,1,0,0)  // EOR
16935ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           || INSN0(9,5) == BITS5(0,0,0,1,1)) // ORN
16936ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && INSN1(15,15) == 0) {
16937ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt bS = INSN0(4,4);
16938ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt rN = INSN0(3,0);
16939ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt rD = INSN1(11,8);
16940ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (!isBadRegT(rN) && !isBadRegT(rD)) {
16941ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         Bool   notArgR = False;
16942ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IROp   op      = Iop_INVALID;
16943ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HChar* nm      = "???";
16944ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         switch (INSN0(9,5)) {
16945ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case BITS5(0,0,0,1,0): op = Iop_Or32;  nm = "orr"; break;
16946ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case BITS5(0,0,0,0,0): op = Iop_And32; nm = "and"; break;
16947ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case BITS5(0,0,0,0,1): op = Iop_And32; nm = "bic";
16948ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                   notArgR = True; break;
16949ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case BITS5(0,0,1,0,0): op = Iop_Xor32; nm = "eor"; break;
16950ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case BITS5(0,0,0,1,1): op = Iop_Or32;  nm = "orn";
16951ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                   notArgR = True; break;
16952ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            default: vassert(0);
16953ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
16954ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp argL  = newTemp(Ity_I32);
16955ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp argR  = newTemp(Ity_I32);
16956ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp res   = newTemp(Ity_I32);
16957ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         Bool   updC  = False;
16958ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         UInt   imm32 = thumbExpandImm_from_I0_I1(&updC, insn0, insn1);
16959ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign(argL, getIRegT(rN));
16960ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign(argR, mkU32(notArgR ? ~imm32 : imm32));
16961ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign(res,  binop(op, mkexpr(argL), mkexpr(argR)));
16962ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putIRegT(rD, mkexpr(res), condT);
16963ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (bS) {
16964ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            IRTemp oldV = newTemp(Ity_I32);
16965ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            IRTemp oldC = newTemp(Ity_I32);
16966ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            assign( oldV, mk_armg_calculate_flag_v() );
16967ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            assign( oldC, updC
16968ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          ? mkU32((imm32 >> 31) & 1)
16969ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          : mk_armg_calculate_flag_c() );
16970ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            setFlags_D1_D2_ND( ARMG_CC_OP_LOGIC, res, oldC, oldV,
16971ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               condT );
16972ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
16973ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("%s%s.w r%u, r%u, #%u\n",
16974ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             nm, bS == 1 ? "s" : "", rD, rN, imm32);
16975ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto decode_success;
16976ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
16977ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
16978ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16979ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* ---------- (T3) ADD{S}.W Rd, Rn, Rm, {shift} ---------- */
16980ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* ---------- (T3) SUB{S}.W Rd, Rn, Rm, {shift} ---------- */
16981ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* ---------- (T3) RSB{S}.W Rd, Rn, Rm, {shift} ---------- */
16982ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (INSN0(15,9) == BITS7(1,1,1,0,1,0,1)
16983ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && (   INSN0(8,5) == BITS4(1,0,0,0)  // add subopc
16984ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           || INSN0(8,5) == BITS4(1,1,0,1)  // sub subopc
16985ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           || INSN0(8,5) == BITS4(1,1,1,0)) // rsb subopc
16986ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && INSN1(15,15) == 0) {
16987ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt rN   = INSN0(3,0);
16988ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt rD   = INSN1(11,8);
16989ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt rM   = INSN1(3,0);
16990ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt bS   = INSN0(4,4);
16991ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt imm5 = (INSN1(14,12) << 2) | INSN1(7,6);
16992ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt how  = INSN1(5,4);
16993ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16994ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Bool valid = !isBadRegT(rD) && !isBadRegT(rN) && !isBadRegT(rM);
16995663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* but allow "add.w reg, sp, reg, lsl #N for N=0,1,2 or 3
16996b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         (T3) "ADD (SP plus register) */
16997ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (!valid && INSN0(8,5) == BITS4(1,0,0,0) // add
16998663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          && rD != 15 && rN == 13 && imm5 <= 3 && how == 0) {
16999ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         valid = True;
17000ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
17001b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      /* also allow "sub.w reg, sp, reg   w/ no shift
17002b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         (T1) "SUB (SP minus register) */
17003b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      if (!valid && INSN0(8,5) == BITS4(1,1,0,1) // sub
17004b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov          && rD != 15 && rN == 13 && imm5 == 0 && how == 0) {
17005ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         valid = True;
17006ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
17007ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (valid) {
17008ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         Bool   swap = False;
17009ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IROp   op   = Iop_INVALID;
17010ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HChar* nm   = "???";
17011ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         switch (INSN0(8,5)) {
17012ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case BITS4(1,0,0,0): op = Iop_Add32; nm = "add"; break;
17013ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case BITS4(1,1,0,1): op = Iop_Sub32; nm = "sub"; break;
17014ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case BITS4(1,1,1,0): op = Iop_Sub32; nm = "rsb";
17015ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                 swap = True; break;
17016ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            default: vassert(0);
17017ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
17018ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
17019ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp argL = newTemp(Ity_I32);
17020ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign(argL, getIRegT(rN));
17021ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
17022ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp rMt = newTemp(Ity_I32);
17023ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign(rMt, getIRegT(rM));
17024ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
17025ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp argR = newTemp(Ity_I32);
17026ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         compute_result_and_C_after_shift_by_imm5(
17027ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            dis_buf, &argR, NULL, rMt, how, imm5, rM
17028ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         );
17029ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
17030ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp res = newTemp(Ity_I32);
17031ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign(res, swap
17032ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     ? binop(op, mkexpr(argR), mkexpr(argL))
17033ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     : binop(op, mkexpr(argL), mkexpr(argR)));
17034ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
17035ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putIRegT(rD, mkexpr(res), condT);
17036ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (bS) {
17037ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            switch (op) {
17038ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               case Iop_Add32:
17039ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  setFlags_D1_D2( ARMG_CC_OP_ADD, argL, argR, condT );
17040ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  break;
17041ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               case Iop_Sub32:
17042ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  if (swap)
17043ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     setFlags_D1_D2( ARMG_CC_OP_SUB, argR, argL, condT );
17044ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  else
17045ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     setFlags_D1_D2( ARMG_CC_OP_SUB, argL, argR, condT );
17046ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  break;
17047ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               default:
17048ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  vassert(0);
17049ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
17050ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
17051ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
17052ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("%s%s.w r%u, r%u, %s\n",
17053ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             nm, bS ? "s" : "", rD, rN, dis_buf);
17054ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto decode_success;
17055ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
17056ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
17057ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
17058ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* ---------- (T3) ADC{S}.W Rd, Rn, Rm, {shift} ---------- */
17059ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* ---------- (T2) SBC{S}.W Rd, Rn, Rm, {shift} ---------- */
17060ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (INSN0(15,9) == BITS7(1,1,1,0,1,0,1)
17061ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && (   INSN0(8,5) == BITS4(1,0,1,0)   // adc subopc
17062ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           || INSN0(8,5) == BITS4(1,0,1,1))  // sbc subopc
17063ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && INSN1(15,15) == 0) {
17064ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* ADC:  Rd = Rn + shifter_operand + oldC */
17065ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* SBC:  Rd = Rn - shifter_operand - (oldC ^ 1) */
17066ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt rN = INSN0(3,0);
17067ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt rD = INSN1(11,8);
17068ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt rM = INSN1(3,0);
17069ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (!isBadRegT(rD) && !isBadRegT(rN) && !isBadRegT(rM)) {
17070ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         UInt bS   = INSN0(4,4);
17071ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         UInt imm5 = (INSN1(14,12) << 2) | INSN1(7,6);
17072ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         UInt how  = INSN1(5,4);
17073ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
17074ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp argL = newTemp(Ity_I32);
17075ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign(argL, getIRegT(rN));
17076ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
17077ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp rMt = newTemp(Ity_I32);
17078ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign(rMt, getIRegT(rM));
17079ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
17080ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp oldC = newTemp(Ity_I32);
17081ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign(oldC, mk_armg_calculate_flag_c());
17082ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
17083ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp argR = newTemp(Ity_I32);
17084ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         compute_result_and_C_after_shift_by_imm5(
17085ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            dis_buf, &argR, NULL, rMt, how, imm5, rM
17086ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         );
17087ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
17088ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HChar* nm  = "???";
17089ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp res = newTemp(Ity_I32);
17090ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         switch (INSN0(8,5)) {
17091ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case BITS4(1,0,1,0): // ADC
17092ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               nm = "adc";
17093ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               assign(res,
17094ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      binop(Iop_Add32,
17095ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            binop(Iop_Add32, mkexpr(argL), mkexpr(argR)),
17096ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            mkexpr(oldC) ));
17097ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               putIRegT(rD, mkexpr(res), condT);
17098ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               if (bS)
17099ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  setFlags_D1_D2_ND( ARMG_CC_OP_ADC,
17100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                     argL, argR, oldC, condT );
17101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
17102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case BITS4(1,0,1,1): // SBC
17103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               nm = "sbc";
17104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               assign(res,
17105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      binop(Iop_Sub32,
17106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            binop(Iop_Sub32, mkexpr(argL), mkexpr(argR)),
17107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            binop(Iop_Xor32, mkexpr(oldC), mkU32(1)) ));
17108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               putIRegT(rD, mkexpr(res), condT);
17109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               if (bS)
17110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  setFlags_D1_D2_ND( ARMG_CC_OP_SBB,
17111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                     argL, argR, oldC, condT );
17112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
17113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            default:
17114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               vassert(0);
17115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
17116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
17117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("%s%s.w r%u, r%u, %s\n",
17118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             nm, bS ? "s" : "", rD, rN, dis_buf);
17119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto decode_success;
17120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
17121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
17122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
17123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* ---------- (T3) AND{S}.W Rd, Rn, Rm, {shift} ---------- */
17124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* ---------- (T3) ORR{S}.W Rd, Rn, Rm, {shift} ---------- */
17125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* ---------- (T3) EOR{S}.W Rd, Rn, Rm, {shift} ---------- */
17126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* ---------- (T3) BIC{S}.W Rd, Rn, Rm, {shift} ---------- */
17127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* ---------- (T1) ORN{S}.W Rd, Rn, Rm, {shift} ---------- */
17128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (INSN0(15,9) == BITS7(1,1,1,0,1,0,1)
17129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && (   INSN0(8,5) == BITS4(0,0,0,0)  // and subopc
17130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           || INSN0(8,5) == BITS4(0,0,1,0)  // orr subopc
17131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           || INSN0(8,5) == BITS4(0,1,0,0)  // eor subopc
17132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           || INSN0(8,5) == BITS4(0,0,0,1)  // bic subopc
17133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           || INSN0(8,5) == BITS4(0,0,1,1)) // orn subopc
17134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && INSN1(15,15) == 0) {
17135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt rN = INSN0(3,0);
17136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt rD = INSN1(11,8);
17137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt rM = INSN1(3,0);
17138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (!isBadRegT(rD) && !isBadRegT(rN) && !isBadRegT(rM)) {
17139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         Bool notArgR = False;
17140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IROp op      = Iop_INVALID;
17141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HChar* nm  = "???";
17142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         switch (INSN0(8,5)) {
17143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case BITS4(0,0,0,0): op = Iop_And32; nm = "and"; break;
17144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case BITS4(0,0,1,0): op = Iop_Or32;  nm = "orr"; break;
17145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case BITS4(0,1,0,0): op = Iop_Xor32; nm = "eor"; break;
17146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case BITS4(0,0,0,1): op = Iop_And32; nm = "bic";
17147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                 notArgR = True; break;
17148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case BITS4(0,0,1,1): op = Iop_Or32; nm = "orn";
17149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                 notArgR = True; break;
17150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            default: vassert(0);
17151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
17152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         UInt bS   = INSN0(4,4);
17153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         UInt imm5 = (INSN1(14,12) << 2) | INSN1(7,6);
17154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         UInt how  = INSN1(5,4);
17155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
17156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp rNt = newTemp(Ity_I32);
17157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign(rNt, getIRegT(rN));
17158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
17159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp rMt = newTemp(Ity_I32);
17160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign(rMt, getIRegT(rM));
17161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
17162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp argR = newTemp(Ity_I32);
17163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp oldC = bS ? newTemp(Ity_I32) : IRTemp_INVALID;
17164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
17165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         compute_result_and_C_after_shift_by_imm5(
17166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            dis_buf, &argR, bS ? &oldC : NULL, rMt, how, imm5, rM
17167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         );
17168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
17169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp res = newTemp(Ity_I32);
17170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (notArgR) {
17171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vassert(op == Iop_And32 || op == Iop_Or32);
17172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            assign(res, binop(op, mkexpr(rNt),
17173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                  unop(Iop_Not32, mkexpr(argR))));
17174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
17175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            assign(res, binop(op, mkexpr(rNt), mkexpr(argR)));
17176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
17177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
17178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putIRegT(rD, mkexpr(res), condT);
17179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (bS) {
17180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            IRTemp oldV = newTemp(Ity_I32);
17181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            assign( oldV, mk_armg_calculate_flag_v() );
17182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            setFlags_D1_D2_ND( ARMG_CC_OP_LOGIC, res, oldC, oldV,
17183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               condT );
17184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
17185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
17186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("%s%s.w r%u, r%u, %s\n",
17187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             nm, bS ? "s" : "", rD, rN, dis_buf);
17188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto decode_success;
17189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
17190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
17191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
17192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* -------------- (T?) LSL{S}.W Rd, Rn, Rm -------------- */
17193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* -------------- (T?) LSR{S}.W Rd, Rn, Rm -------------- */
17194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* -------------- (T?) ASR{S}.W Rd, Rn, Rm -------------- */
17195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* -------------- (T?) ROR{S}.W Rd, Rn, Rm -------------- */
17196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (INSN0(15,7) == BITS9(1,1,1,1,1,0,1,0,0)
17197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && INSN1(15,12) == BITS4(1,1,1,1)
17198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && INSN1(7,4) == BITS4(0,0,0,0)) {
17199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt how = INSN0(6,5); // standard encoding
17200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt rN  = INSN0(3,0);
17201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt rD  = INSN1(11,8);
17202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt rM  = INSN1(3,0);
17203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt bS  = INSN0(4,4);
17204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Bool valid = !isBadRegT(rN) && !isBadRegT(rM) && !isBadRegT(rD);
17205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (valid) {
17206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp rNt    = newTemp(Ity_I32);
17207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp rMt    = newTemp(Ity_I32);
17208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp res    = newTemp(Ity_I32);
17209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp oldC   = bS ? newTemp(Ity_I32) : IRTemp_INVALID;
17210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp oldV   = bS ? newTemp(Ity_I32) : IRTemp_INVALID;
17211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HChar* nms[4] = { "lsl", "lsr", "asr", "ror" };
17212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HChar* nm     = nms[how];
17213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign(rNt, getIRegT(rN));
17214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign(rMt, getIRegT(rM));
17215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         compute_result_and_C_after_shift_by_reg(
17216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            dis_buf, &res, bS ? &oldC : NULL,
17217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            rNt, how, rMt, rN, rM
17218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         );
17219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (bS)
17220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            assign(oldV, mk_armg_calculate_flag_v());
17221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putIRegT(rD, mkexpr(res), condT);
17222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (bS) {
17223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            setFlags_D1_D2_ND( ARMG_CC_OP_LOGIC, res, oldC, oldV,
17224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               condT );
17225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
17226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("%s%s.w r%u, r%u, r%u\n",
17227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             nm, bS ? "s" : "", rD, rN, rM);
17228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto decode_success;
17229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
17230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
17231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
17232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* ------------ (T?) MOV{S}.W Rd, Rn, {shift} ------------ */
17233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* ------------ (T?) MVN{S}.W Rd, Rn, {shift} ------------ */
17234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if ((INSN0(15,0) & 0xFFCF) == 0xEA4F
17235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && INSN1(15,15) == 0) {
17236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt rD = INSN1(11,8);
17237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt rN = INSN1(3,0);
17238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (!isBadRegT(rD) && !isBadRegT(rN)) {
17239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         UInt bS    = INSN0(4,4);
17240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         UInt isMVN = INSN0(5,5);
17241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         UInt imm5  = (INSN1(14,12) << 2) | INSN1(7,6);
17242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         UInt how   = INSN1(5,4);
17243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
17244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp rNt = newTemp(Ity_I32);
17245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign(rNt, getIRegT(rN));
17246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
17247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp oldRn = newTemp(Ity_I32);
17248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp oldC  = bS ? newTemp(Ity_I32) : IRTemp_INVALID;
17249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         compute_result_and_C_after_shift_by_imm5(
17250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            dis_buf, &oldRn, bS ? &oldC : NULL, rNt, how, imm5, rN
17251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         );
17252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
17253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp res = newTemp(Ity_I32);
17254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign(res, isMVN ? unop(Iop_Not32, mkexpr(oldRn))
17255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           : mkexpr(oldRn));
17256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
17257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putIRegT(rD, mkexpr(res), condT);
17258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (bS) {
17259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            IRTemp oldV = newTemp(Ity_I32);
17260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            assign( oldV, mk_armg_calculate_flag_v() );
17261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            setFlags_D1_D2_ND( ARMG_CC_OP_LOGIC, res, oldC, oldV, condT);
17262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
17263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("%s%s.w r%u, %s\n",
17264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             isMVN ? "mvn" : "mov", bS ? "s" : "", rD, dis_buf);
17265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto decode_success;
17266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
17267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
17268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
17269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* -------------- (T?) TST.W Rn, Rm, {shift} -------------- */
17270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* -------------- (T?) TEQ.W Rn, Rm, {shift} -------------- */
17271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (INSN0(15,9) == BITS7(1,1,1,0,1,0,1)
17272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && (   INSN0(8,4) == BITS5(0,0,0,0,1)  // TST
17273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           || INSN0(8,4) == BITS5(0,1,0,0,1)) // TEQ
17274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && INSN1(15,15) == 0
17275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && INSN1(11,8) == BITS4(1,1,1,1)) {
17276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt rN = INSN0(3,0);
17277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt rM = INSN1(3,0);
17278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (!isBadRegT(rN) && !isBadRegT(rM)) {
17279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         Bool isTST = INSN0(8,4) == BITS5(0,0,0,0,1);
17280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
17281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         UInt how  = INSN1(5,4);
17282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         UInt imm5 = (INSN1(14,12) << 2) | INSN1(7,6);
17283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
17284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp argL = newTemp(Ity_I32);
17285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign(argL, getIRegT(rN));
17286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
17287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp rMt = newTemp(Ity_I32);
17288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign(rMt, getIRegT(rM));
17289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
17290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp argR = newTemp(Ity_I32);
17291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp oldC = newTemp(Ity_I32);
17292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         compute_result_and_C_after_shift_by_imm5(
17293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            dis_buf, &argR, &oldC, rMt, how, imm5, rM
17294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         );
17295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
17296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp oldV = newTemp(Ity_I32);
17297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( oldV, mk_armg_calculate_flag_v() );
17298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
17299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp res = newTemp(Ity_I32);
17300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign(res, binop(isTST ? Iop_And32 : Iop_Xor32,
17301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           mkexpr(argL), mkexpr(argR)));
17302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
17303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         setFlags_D1_D2_ND( ARMG_CC_OP_LOGIC, res, oldC, oldV,
17304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            condT );
17305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("%s.w r%u, %s\n", isTST ? "tst" : "teq", rN, dis_buf);
17306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto decode_success;
17307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
17308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
17309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
17310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* -------------- (T3) CMP.W Rn, Rm, {shift} -------------- */
17311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* -------------- (T2) CMN.W Rn, Rm, {shift} -------------- */
17312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (INSN0(15,9) == BITS7(1,1,1,0,1,0,1)
17313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && (   INSN0(8,4) == BITS5(1,1,0,1,1)  // CMP
17314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           || INSN0(8,4) == BITS5(1,0,0,0,1)) // CMN
17315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && INSN1(15,15) == 0
17316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && INSN1(11,8) == BITS4(1,1,1,1)) {
17317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt rN = INSN0(3,0);
17318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt rM = INSN1(3,0);
17319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (!isBadRegT(rN) && !isBadRegT(rM)) {
17320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         Bool isCMN = INSN0(8,4) == BITS5(1,0,0,0,1);
17321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         UInt how   = INSN1(5,4);
17322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         UInt imm5  = (INSN1(14,12) << 2) | INSN1(7,6);
17323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
17324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp argL = newTemp(Ity_I32);
17325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign(argL, getIRegT(rN));
17326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
17327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp rMt = newTemp(Ity_I32);
17328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign(rMt, getIRegT(rM));
17329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
17330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp argR = newTemp(Ity_I32);
17331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         compute_result_and_C_after_shift_by_imm5(
17332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            dis_buf, &argR, NULL, rMt, how, imm5, rM
17333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         );
17334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
17335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         setFlags_D1_D2( isCMN ? ARMG_CC_OP_ADD : ARMG_CC_OP_SUB,
17336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         argL, argR, condT );
17337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
17338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("%s.w r%u, %s\n", isCMN ? "cmn" : "cmp", rN, dis_buf);
17339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto decode_success;
17340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
17341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
17342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
17343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* -------------- (T2) MOV{S}.W Rd, #constT -------------- */
17344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* -------------- (T2) MVN{S}.W Rd, #constT -------------- */
17345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (INSN0(15,11) == BITS5(1,1,1,1,0)
17346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && (   INSN0(9,5) == BITS5(0,0,0,1,0)  // MOV
17347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           || INSN0(9,5) == BITS5(0,0,0,1,1)) // MVN
17348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && INSN0(3,0) == BITS4(1,1,1,1)
17349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && INSN1(15,15) == 0) {
17350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt rD = INSN1(11,8);
17351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (!isBadRegT(rD)) {
17352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         Bool   updC  = False;
17353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         UInt   bS    = INSN0(4,4);
17354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         Bool   isMVN = INSN0(5,5) == 1;
17355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         UInt   imm32 = thumbExpandImm_from_I0_I1(&updC, insn0, insn1);
17356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp res   = newTemp(Ity_I32);
17357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign(res, mkU32(isMVN ? ~imm32 : imm32));
17358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putIRegT(rD, mkexpr(res), condT);
17359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (bS) {
17360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            IRTemp oldV = newTemp(Ity_I32);
17361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            IRTemp oldC = newTemp(Ity_I32);
17362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            assign( oldV, mk_armg_calculate_flag_v() );
17363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            assign( oldC, updC
17364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          ? mkU32((imm32 >> 31) & 1)
17365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          : mk_armg_calculate_flag_c() );
17366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            setFlags_D1_D2_ND( ARMG_CC_OP_LOGIC, res, oldC, oldV,
17367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               condT );
17368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
17369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("%s%s.w r%u, #%u\n",
17370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             isMVN ? "mvn" : "mov", bS ? "s" : "", rD, imm32);
17371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto decode_success;
17372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
17373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
17374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
17375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* -------------- (T3) MOVW Rd, #imm16 -------------- */
17376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (INSN0(15,11) == BITS5(1,1,1,1,0)
17377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && INSN0(9,4) == BITS6(1,0,0,1,0,0)
17378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && INSN1(15,15) == 0) {
17379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt rD = INSN1(11,8);
17380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (!isBadRegT(rD)) {
17381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         UInt imm16 = (INSN0(3,0) << 12) | (INSN0(10,10) << 11)
17382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      | (INSN1(14,12) << 8) | INSN1(7,0);
17383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putIRegT(rD, mkU32(imm16), condT);
17384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("movw r%u, #%u\n", rD, imm16);
17385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto decode_success;
17386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
17387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
17388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
17389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* ---------------- MOVT Rd, #imm16 ---------------- */
17390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (INSN0(15,11) == BITS5(1,1,1,1,0)
17391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && INSN0(9,4) == BITS6(1,0,1,1,0,0)
17392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && INSN1(15,15) == 0) {
17393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt rD = INSN1(11,8);
17394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (!isBadRegT(rD)) {
17395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         UInt imm16 = (INSN0(3,0) << 12) | (INSN0(10,10) << 11)
17396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      | (INSN1(14,12) << 8) | INSN1(7,0);
17397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp res = newTemp(Ity_I32);
17398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign(res,
17399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                binop(Iop_Or32,
17400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      binop(Iop_And32, getIRegT(rD), mkU32(0xFFFF)),
17401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      mkU32(imm16 << 16)));
17402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putIRegT(rD, mkexpr(res), condT);
17403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("movt r%u, #%u\n", rD, imm16);
17404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto decode_success;
17405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
17406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
17407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
17408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* ---------------- LD/ST reg+/-#imm8 ---------------- */
17409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Loads and stores of the form:
17410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         op  Rt, [Rn, #-imm8]      or
17411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         op  Rt, [Rn], #+/-imm8    or
17412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         op  Rt, [Rn, #+/-imm8]!
17413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      where op is one of
17414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ldrb ldrh ldr  ldrsb ldrsh
17415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         strb strh str
17416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   */
17417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (INSN0(15,9) == BITS7(1,1,1,1,1,0,0) && INSN1(11,11) == 1) {
17418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Bool   valid  = True;
17419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Bool   syned  = False;
17420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Bool   isST   = False;
17421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRType ty     = Ity_I8;
17422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HChar* nm     = "???";
17423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
17424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch (INSN0(8,4)) {
17425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case BITS5(0,0,0,0,0):   // strb
17426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            nm = "strb"; isST = True; break;
17427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case BITS5(0,0,0,0,1):   // ldrb
17428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            nm = "ldrb"; break;
17429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case BITS5(1,0,0,0,1):   // ldrsb
17430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            nm = "ldrsb"; syned = True; break;
17431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case BITS5(0,0,0,1,0):   // strh
17432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            nm = "strh"; ty = Ity_I16; isST = True; break;
17433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case BITS5(0,0,0,1,1):   // ldrh
17434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            nm = "ldrh"; ty = Ity_I16; break;
17435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case BITS5(1,0,0,1,1):   // ldrsh
17436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            nm = "ldrsh"; ty = Ity_I16; syned = True; break;
17437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case BITS5(0,0,1,0,0):   // str
17438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            nm = "str"; ty = Ity_I32; isST = True; break;
17439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case BITS5(0,0,1,0,1):
17440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            nm = "ldr"; ty = Ity_I32; break;  // ldr
17441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         default:
17442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            valid = False; break;
17443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
17444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
17445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt rN      = INSN0(3,0);
17446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt rT      = INSN1(15,12);
17447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt bP      = INSN1(10,10);
17448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt bU      = INSN1(9,9);
17449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt bW      = INSN1(8,8);
17450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt imm8    = INSN1(7,0);
17451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Bool loadsPC = False;
17452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
17453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (valid) {
17454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (bP == 1 && bU == 1 && bW == 0)
17455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            valid = False;
17456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (bP == 0 && bW == 0)
17457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            valid = False;
17458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (rN == 15)
17459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            valid = False;
17460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (bW == 1 && rN == rT)
17461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            valid = False;
17462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (ty == Ity_I8 || ty == Ity_I16) {
17463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (isBadRegT(rT))
17464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               valid = False;
17465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
17466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* ty == Ity_I32 */
17467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (isST && rT == 15)
17468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               valid = False;
17469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (!isST && rT == 15)
17470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               loadsPC = True;
17471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
17472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
17473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
17474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (valid) {
17475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         // if it's a branch, it can't happen in the middle of an IT block
17476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (loadsPC)
17477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            gen_SIGILL_T_if_in_but_NLI_ITBlock(old_itstate, new_itstate);
17478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         // go uncond
17479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         mk_skip_over_T32_if_cond_is_false(condT);
17480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         condT = IRTemp_INVALID;
17481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         // now uncond
17482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
17483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp preAddr = newTemp(Ity_I32);
17484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign(preAddr, getIRegT(rN));
17485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
17486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp postAddr = newTemp(Ity_I32);
17487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign(postAddr, binop(bU == 1 ? Iop_Add32 : Iop_Sub32,
17488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                mkexpr(preAddr), mkU32(imm8)));
17489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
17490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp transAddr = bP == 1 ? postAddr : preAddr;
17491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
17492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (isST) {
17493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
17494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             /* Store.  If necessary, update the base register before
17495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                the store itself, so that the common idiom of "str rX,
17496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                [sp, #-4]!" (store rX at sp-4, then do new sp = sp-4,
17497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                a.k.a "push rX") doesn't cause Memcheck to complain
17498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                that the access is below the stack pointer.  Also, not
17499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                updating sp before the store confuses Valgrind's
17500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                dynamic stack-extending logic.  So do it before the
17501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                store.  Hence we need to snarf the store data before
17502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                doing the basereg update. */
17503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
17504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* get hold of the data to be stored */
17505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            IRTemp oldRt = newTemp(Ity_I32);
17506ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            assign(oldRt, getIRegT(rT));
17507ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
17508ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* Update Rn if necessary. */
17509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (bW == 1) {
17510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               vassert(rN != rT); // assured by validity check above
17511ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               putIRegT(rN, mkexpr(postAddr), IRTemp_INVALID);
17512ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
17513ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
17514ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* generate the transfer */
17515ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            switch (ty) {
17516ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               case Ity_I8:
17517ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  storeLE(mkexpr(transAddr),
17518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                 unop(Iop_32to8, mkexpr(oldRt)));
17519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  break;
17520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               case Ity_I16:
17521ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  storeLE(mkexpr(transAddr),
17522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          unop(Iop_32to16, mkexpr(oldRt)));
17523ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  break;
17524ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              case Ity_I32:
17525ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  storeLE(mkexpr(transAddr), mkexpr(oldRt));
17526ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  break;
17527ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              default:
17528ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 vassert(0);
17529ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
17530ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
17531ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
17532ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
17533ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* Load. */
17534ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
17535ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* generate the transfer */
17536ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            IRTemp newRt = newTemp(Ity_I32);
17537ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            IROp   widen = Iop_INVALID;
17538ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            switch (ty) {
17539ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               case Ity_I8:
17540ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  widen = syned ? Iop_8Sto32 : Iop_8Uto32; break;
17541ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               case Ity_I16:
17542ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  widen = syned ? Iop_16Sto32 : Iop_16Uto32; break;
17543ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               case Ity_I32:
17544ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  break;
17545ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               default:
17546ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  vassert(0);
17547ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
17548ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (widen == Iop_INVALID) {
17549ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               assign(newRt, loadLE(ty, mkexpr(transAddr)));
17550ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else {
17551ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               assign(newRt, unop(widen, loadLE(ty, mkexpr(transAddr))));
17552ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
17553ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (loadsPC) {
17554ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               vassert(rT == 15);
17555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               llPutIReg(rT, mkexpr(newRt));
17556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else {
17557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               putIRegT(rT, mkexpr(newRt), IRTemp_INVALID);
17558ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
17559ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
17560ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* Update Rn if necessary. */
17561ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (bW == 1) {
17562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               vassert(rN != rT); // assured by validity check above
17563ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               putIRegT(rN, mkexpr(postAddr), IRTemp_INVALID);
17564ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
17565663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
17566663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            if (loadsPC) {
17567663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               /* Presumably this is an interworking branch. */
17568663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               vassert(rN != 15); // assured by validity check above
17569663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               llPutIReg(15, mkexpr(newRt));
17570663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               dres.jk_StopHere = Ijk_Boring;  /* or _Ret ? */
17571663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               dres.whatNext    = Dis_StopHere;
17572663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            }
17573ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
17574ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
17575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (bP == 1 && bW == 0) {
17576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            DIP("%s.w r%u, [r%u, #%c%u]\n",
17577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                nm, rT, rN, bU ? '+' : '-', imm8);
17578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
17579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         else if (bP == 1 && bW == 1) {
17580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            DIP("%s.w r%u, [r%u, #%c%u]!\n",
17581ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                nm, rT, rN, bU ? '+' : '-', imm8);
17582ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
17583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         else {
17584ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vassert(bP == 0 && bW == 1);
17585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            DIP("%s.w r%u, [r%u], #%c%u\n",
17586ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                nm, rT, rN, bU ? '+' : '-', imm8);
17587ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
17588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
17589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto decode_success;
17590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
17591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
17592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
17593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* ------------- LD/ST reg+(reg<<imm2) ------------- */
17594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Loads and stores of the form:
17595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         op  Rt, [Rn, Rm, LSL #imm8]
17596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      where op is one of
17597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ldrb ldrh ldr  ldrsb ldrsh
17598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         strb strh str
17599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   */
17600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (INSN0(15,9) == BITS7(1,1,1,1,1,0,0)
17601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && INSN1(11,6) == BITS6(0,0,0,0,0,0)) {
17602ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Bool   valid  = True;
17603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Bool   syned  = False;
17604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Bool   isST   = False;
17605ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRType ty     = Ity_I8;
17606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HChar* nm     = "???";
17607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
17608ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch (INSN0(8,4)) {
17609ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case BITS5(0,0,0,0,0):   // strb
17610ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            nm = "strb"; isST = True; break;
17611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case BITS5(0,0,0,0,1):   // ldrb
17612ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            nm = "ldrb"; break;
17613ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case BITS5(1,0,0,0,1):   // ldrsb
17614ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            nm = "ldrsb"; syned = True; break;
17615ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case BITS5(0,0,0,1,0):   // strh
17616ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            nm = "strh"; ty = Ity_I16; isST = True; break;
17617ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case BITS5(0,0,0,1,1):   // ldrh
17618ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            nm = "ldrh"; ty = Ity_I16; break;
17619ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case BITS5(1,0,0,1,1):   // ldrsh
17620ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            nm = "ldrsh"; ty = Ity_I16; syned = True; break;
17621ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case BITS5(0,0,1,0,0):   // str
17622ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            nm = "str"; ty = Ity_I32; isST = True; break;
17623ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case BITS5(0,0,1,0,1):
17624ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            nm = "ldr"; ty = Ity_I32; break;  // ldr
17625ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         default:
17626ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            valid = False; break;
17627ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
17628ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
17629ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt rN      = INSN0(3,0);
17630ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt rM      = INSN1(3,0);
17631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt rT      = INSN1(15,12);
17632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt imm2    = INSN1(5,4);
17633ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Bool loadsPC = False;
17634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
17635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (ty == Ity_I8 || ty == Ity_I16) {
17636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* all 8- and 16-bit load and store cases have the
17637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            same exclusion set. */
17638ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (rN == 15 || isBadRegT(rT) || isBadRegT(rM))
17639ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            valid = False;
17640ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else {
17641ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(ty == Ity_I32);
17642ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (rN == 15 || isBadRegT(rM))
17643ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            valid = False;
17644ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (isST && rT == 15)
17645ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            valid = False;
17646ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* If it is a load and rT is 15, that's only allowable if we
17647ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            not in an IT block, or are the last in it.  Need to insert
17648ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            a dynamic check for that. */
17649ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (!isST && rT == 15)
17650ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            loadsPC = True;
17651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
17652ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
17653ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (valid) {
17654ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         // if it's a branch, it can't happen in the middle of an IT block
17655ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (loadsPC)
17656ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            gen_SIGILL_T_if_in_but_NLI_ITBlock(old_itstate, new_itstate);
17657ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         // go uncond
17658ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         mk_skip_over_T32_if_cond_is_false(condT);
17659ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         condT = IRTemp_INVALID;
17660ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         // now uncond
17661ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
17662ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp transAddr = newTemp(Ity_I32);
17663ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign(transAddr,
17664ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                binop( Iop_Add32,
17665ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       getIRegT(rN),
17666ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       binop(Iop_Shl32, getIRegT(rM), mkU8(imm2)) ));
17667ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
17668ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (isST) {
17669ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            IRTemp oldRt = newTemp(Ity_I32);
17670ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            assign(oldRt, getIRegT(rT));
17671ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            switch (ty) {
17672ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               case Ity_I8:
17673ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  storeLE(mkexpr(transAddr),
17674ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                 unop(Iop_32to8, mkexpr(oldRt)));
17675ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  break;
17676ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               case Ity_I16:
17677ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  storeLE(mkexpr(transAddr),
17678ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          unop(Iop_32to16, mkexpr(oldRt)));
17679ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  break;
17680ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              case Ity_I32:
17681ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  storeLE(mkexpr(transAddr), mkexpr(oldRt));
17682ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  break;
17683ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              default:
17684ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 vassert(0);
17685ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
17686ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
17687ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            IRTemp newRt = newTemp(Ity_I32);
17688ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            IROp   widen = Iop_INVALID;
17689ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            switch (ty) {
17690ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               case Ity_I8:
17691ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  widen = syned ? Iop_8Sto32 : Iop_8Uto32; break;
17692ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               case Ity_I16:
17693ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  widen = syned ? Iop_16Sto32 : Iop_16Uto32; break;
17694ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               case Ity_I32:
17695ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  break;
17696ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               default:
17697ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  vassert(0);
17698ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
17699ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (widen == Iop_INVALID) {
17700ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               assign(newRt, loadLE(ty, mkexpr(transAddr)));
17701ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else {
17702ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               assign(newRt, unop(widen, loadLE(ty, mkexpr(transAddr))));
17703ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
17704ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
17705ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* If we're loading the PC, putIRegT will assert.  So go
17706ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               direct via llPutIReg.  In all other cases use putIRegT
17707ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               as it is safer (although could simply use llPutIReg for
17708ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               _all_ cases here.) */
17709ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (loadsPC) {
17710ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               vassert(rT == 15);
17711ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               llPutIReg(rT, mkexpr(newRt));
17712ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else {
17713ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               putIRegT(rT, mkexpr(newRt), IRTemp_INVALID);
17714ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
17715ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
17716ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (loadsPC) {
17717ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               /* Presumably this is an interworking branch. */
17718663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               llPutIReg(15, mkexpr(newRt));
17719663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               dres.jk_StopHere = Ijk_Boring;  /* or _Ret ? */
17720663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               dres.whatNext    = Dis_StopHere;
17721ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
17722ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
17723ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
17724ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("%s.w r%u, [r%u, r%u, LSL #%u]\n",
17725ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             nm, rT, rN, rM, imm2);
17726ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
17727ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto decode_success;
17728ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
17729ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
17730ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
17731ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* --------------- LD/ST reg+imm12 --------------- */
17732ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Loads and stores of the form:
17733ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         op  Rt, [Rn, +#imm12]
17734ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      where op is one of
17735ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ldrb ldrh ldr  ldrsb ldrsh
17736ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         strb strh str
17737ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   */
17738ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (INSN0(15,9) == BITS7(1,1,1,1,1,0,0)) {
17739ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Bool   valid  = True;
17740ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Bool   syned  = False;
17741ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Bool   isST   = False;
17742ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRType ty     = Ity_I8;
17743ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HChar* nm     = "???";
17744ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
17745ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch (INSN0(8,4)) {
17746ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case BITS5(0,1,0,0,0):   // strb
17747ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            nm = "strb"; isST = True; break;
17748ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case BITS5(0,1,0,0,1):   // ldrb
17749ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            nm = "ldrb"; break;
17750ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case BITS5(1,1,0,0,1):   // ldrsb
17751ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            nm = "ldrsb"; syned = True; break;
17752ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case BITS5(0,1,0,1,0):   // strh
17753ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            nm = "strh"; ty = Ity_I16; isST = True; break;
17754ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case BITS5(0,1,0,1,1):   // ldrh
17755ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            nm = "ldrh"; ty = Ity_I16; break;
17756ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case BITS5(1,1,0,1,1):   // ldrsh
17757ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            nm = "ldrsh"; ty = Ity_I16; syned = True; break;
17758ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case BITS5(0,1,1,0,0):   // str
17759ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            nm = "str"; ty = Ity_I32; isST = True; break;
17760ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case BITS5(0,1,1,0,1):
17761ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            nm = "ldr"; ty = Ity_I32; break;  // ldr
17762ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         default:
17763ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            valid = False; break;
17764ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
17765ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
17766ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt rN      = INSN0(3,0);
17767ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt rT      = INSN1(15,12);
17768ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt imm12   = INSN1(11,0);
17769ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Bool loadsPC = False;
17770ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
17771ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (ty == Ity_I8 || ty == Ity_I16) {
17772ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* all 8- and 16-bit load and store cases have the
17773ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            same exclusion set. */
17774ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (rN == 15 || isBadRegT(rT))
17775ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            valid = False;
17776ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else {
17777ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(ty == Ity_I32);
17778ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (isST) {
17779ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (rN == 15 || rT == 15)
17780ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               valid = False;
17781ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
17782ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* For a 32-bit load, rT == 15 is only allowable if we not
17783ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               in an IT block, or are the last in it.  Need to insert
17784ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               a dynamic check for that.  Also, in this particular
17785ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               case, rN == 15 is allowable.  In this case however, the
17786ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               value obtained for rN is (apparently)
17787ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               "word-align(address of current insn + 4)". */
17788ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (rT == 15)
17789ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               loadsPC = True;
17790ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
17791ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
17792ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
17793ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (valid) {
17794ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         // if it's a branch, it can't happen in the middle of an IT block
17795ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (loadsPC)
17796ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            gen_SIGILL_T_if_in_but_NLI_ITBlock(old_itstate, new_itstate);
17797ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         // go uncond
17798ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         mk_skip_over_T32_if_cond_is_false(condT);
17799ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         condT = IRTemp_INVALID;
17800ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         // now uncond
17801ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
17802ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp rNt = newTemp(Ity_I32);
17803ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (rN == 15) {
17804ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vassert(ty == Ity_I32 && !isST);
17805ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            assign(rNt, binop(Iop_And32, getIRegT(rN), mkU32(~3)));
17806ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
17807ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            assign(rNt, getIRegT(rN));
17808ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
17809ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
17810ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp transAddr = newTemp(Ity_I32);
17811ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign(transAddr,
17812ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                binop( Iop_Add32, mkexpr(rNt), mkU32(imm12) ));
17813ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
17814ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (isST) {
17815ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            IRTemp oldRt = newTemp(Ity_I32);
17816ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            assign(oldRt, getIRegT(rT));
17817ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            switch (ty) {
17818ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               case Ity_I8:
17819ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  storeLE(mkexpr(transAddr),
17820ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                 unop(Iop_32to8, mkexpr(oldRt)));
17821ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  break;
17822ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               case Ity_I16:
17823ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  storeLE(mkexpr(transAddr),
17824ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          unop(Iop_32to16, mkexpr(oldRt)));
17825ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  break;
17826ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              case Ity_I32:
17827ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  storeLE(mkexpr(transAddr), mkexpr(oldRt));
17828ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  break;
17829ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              default:
17830ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 vassert(0);
17831ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
17832ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
17833ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            IRTemp newRt = newTemp(Ity_I32);
17834ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            IROp   widen = Iop_INVALID;
17835ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            switch (ty) {
17836ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               case Ity_I8:
17837ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  widen = syned ? Iop_8Sto32 : Iop_8Uto32; break;
17838ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               case Ity_I16:
17839ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  widen = syned ? Iop_16Sto32 : Iop_16Uto32; break;
17840ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               case Ity_I32:
17841ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  break;
17842ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               default:
17843ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  vassert(0);
17844ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
17845ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (widen == Iop_INVALID) {
17846ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               assign(newRt, loadLE(ty, mkexpr(transAddr)));
17847ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else {
17848ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               assign(newRt, unop(widen, loadLE(ty, mkexpr(transAddr))));
17849ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
17850ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            putIRegT(rT, mkexpr(newRt), IRTemp_INVALID);
17851ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
17852ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (loadsPC) {
17853ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               /* Presumably this is an interworking branch. */
17854ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               irsb->next = mkexpr(newRt);
17855ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               irsb->jumpkind = Ijk_Boring;  /* or _Ret ? */
17856ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               dres.whatNext  = Dis_StopHere;
17857ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
17858ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
17859ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
17860ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("%s.w r%u, [r%u, +#%u]\n", nm, rT, rN, imm12);
17861ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
17862ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto decode_success;
17863ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
17864ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
17865ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
17866ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* -------------- LDRD/STRD reg+/-#imm8 -------------- */
17867ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Doubleword loads and stores of the form:
17868ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ldrd/strd  Rt, Rt2, [Rn, #-imm8]      or
17869ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ldrd/strd  Rt, Rt2, [Rn], #+/-imm8    or
17870ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ldrd/strd  Rt, Rt2, [Rn, #+/-imm8]!
17871ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   */
17872ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (INSN0(15,9) == BITS7(1,1,1,0,1,0,0) && INSN0(6,6) == 1) {
17873ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt bP   = INSN0(8,8);
17874ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt bU   = INSN0(7,7);
17875ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt bW   = INSN0(5,5);
17876ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt bL   = INSN0(4,4);  // 1: load  0: store
17877ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt rN   = INSN0(3,0);
17878ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt rT   = INSN1(15,12);
17879ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt rT2  = INSN1(11,8);
17880ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt imm8 = INSN1(7,0);
17881ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
17882ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Bool valid = True;
17883ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (bP == 0 && bW == 0)                 valid = False;
17884ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (bW == 1 && (rN == rT || rN == rT2)) valid = False;
17885ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (isBadRegT(rT) || isBadRegT(rT2))    valid = False;
17886ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (rN == 15)                           valid = False;
17887ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (bL == 1 && rT == rT2)               valid = False;
17888ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
17889ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (valid) {
17890ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         // go uncond
17891ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         mk_skip_over_T32_if_cond_is_false(condT);
17892ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         condT = IRTemp_INVALID;
17893ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         // now uncond
17894ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
17895ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp preAddr = newTemp(Ity_I32);
17896ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign(preAddr, getIRegT(rN));
17897ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
17898ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp postAddr = newTemp(Ity_I32);
17899ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign(postAddr, binop(bU == 1 ? Iop_Add32 : Iop_Sub32,
17900ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                mkexpr(preAddr), mkU32(imm8 << 2)));
17901ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
17902ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp transAddr = bP == 1 ? postAddr : preAddr;
17903ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
17904ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (bL == 0) {
17905ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            IRTemp oldRt  = newTemp(Ity_I32);
17906ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            IRTemp oldRt2 = newTemp(Ity_I32);
17907ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            assign(oldRt,  getIRegT(rT));
17908ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            assign(oldRt2, getIRegT(rT2));
17909ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            storeLE(mkexpr(transAddr),
17910ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    mkexpr(oldRt));
17911ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            storeLE(binop(Iop_Add32, mkexpr(transAddr), mkU32(4)),
17912ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    mkexpr(oldRt2));
17913ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
17914ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            IRTemp newRt  = newTemp(Ity_I32);
17915ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            IRTemp newRt2 = newTemp(Ity_I32);
17916ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            assign(newRt,
17917ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   loadLE(Ity_I32,
17918ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          mkexpr(transAddr)));
17919ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            assign(newRt2,
17920ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   loadLE(Ity_I32,
17921ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          binop(Iop_Add32, mkexpr(transAddr), mkU32(4))));
17922ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            putIRegT(rT,  mkexpr(newRt), IRTemp_INVALID);
17923ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            putIRegT(rT2, mkexpr(newRt2), IRTemp_INVALID);
17924ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
17925ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
17926ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (bW == 1) {
17927ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            putIRegT(rN, mkexpr(postAddr), IRTemp_INVALID);
17928ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
17929ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
17930ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HChar* nm = bL ? "ldrd" : "strd";
17931ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
17932ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (bP == 1 && bW == 0) {
17933ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            DIP("%s.w r%u, r%u, [r%u, #%c%u]\n",
17934ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                nm, rT, rT2, rN, bU ? '+' : '-', imm8 << 2);
17935ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
17936ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         else if (bP == 1 && bW == 1) {
17937ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            DIP("%s.w r%u, r%u, [r%u, #%c%u]!\n",
17938ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                nm, rT, rT2, rN, bU ? '+' : '-', imm8 << 2);
17939ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
17940ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         else {
17941ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vassert(bP == 0 && bW == 1);
17942ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            DIP("%s.w r%u, r%u, [r%u], #%c%u\n",
17943ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                nm, rT, rT2, rN, bU ? '+' : '-', imm8 << 2);
17944ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
17945ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
17946ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto decode_success;
17947ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
17948ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
17949ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
17950ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* -------------- (T3) Bcond.W label -------------- */
17951ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* This variant carries its own condition, so can't be part of an
17952ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IT block ... */
17953ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (INSN0(15,11) == BITS5(1,1,1,1,0)
17954ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && INSN1(15,14) == BITS2(1,0)
17955ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && INSN1(12,12) == 0) {
17956ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt cond = INSN0(9,6);
17957ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (cond != ARMCondAL && cond != ARMCondNV) {
17958ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         Int simm21
17959ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            =   (INSN0(10,10) << (1 + 1 + 6 + 11 + 1))
17960ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              | (INSN1(11,11) << (1 + 6 + 11 + 1))
17961ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              | (INSN1(13,13) << (6 + 11 + 1))
17962ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              | (INSN0(5,0)   << (11 + 1))
17963ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              | (INSN1(10,0)  << 1);
17964ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         simm21 = (simm21 << 11) >> 11;
17965ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
17966ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(0 == (guest_R15_curr_instr_notENC & 1));
17967ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         UInt dst = simm21 + guest_R15_curr_instr_notENC + 4;
17968ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
17969ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Not allowed in an IT block; SIGILL if so. */
17970ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         gen_SIGILL_T_if_in_ITBlock(old_itstate, new_itstate);
17971ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
17972ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp kondT = newTemp(Ity_I32);
17973ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( kondT, mk_armg_calculate_condition(cond) );
17974ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         stmt( IRStmt_Exit( unop(Iop_32to1, mkexpr(kondT)),
17975ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            Ijk_Boring,
17976663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                            IRConst_U32(dst | 1/*CPSR.T*/),
17977663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                            OFFB_R15T ));
17978663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         llPutIReg(15, mkU32( (guest_R15_curr_instr_notENC + 4)
17979663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                              | 1 /*CPSR.T*/ ));
17980663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         dres.jk_StopHere = Ijk_Boring;
17981663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         dres.whatNext    = Dis_StopHere;
17982ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("b%s.w 0x%x\n", nCC(cond), dst);
17983ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto decode_success;
17984ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
17985ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
17986ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
17987ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* ---------------- (T4) B.W label ---------------- */
17988ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* ... whereas this variant doesn't carry its own condition, so it
17989ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      has to be either unconditional or the conditional by virtue of
17990ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      being the last in an IT block.  The upside is that there's 4
17991ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      more bits available for the jump offset, so it has a 16-times
17992ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      greater branch range than the T3 variant. */
17993ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (INSN0(15,11) == BITS5(1,1,1,1,0)
17994ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && INSN1(15,14) == BITS2(1,0)
17995ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && INSN1(12,12) == 1) {
17996ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (1) {
17997ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         UInt bS  = INSN0(10,10);
17998ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         UInt bJ1 = INSN1(13,13);
17999ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         UInt bJ2 = INSN1(11,11);
18000ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         UInt bI1 = 1 ^ (bJ1 ^ bS);
18001ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         UInt bI2 = 1 ^ (bJ2 ^ bS);
18002ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         Int simm25
18003ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            =   (bS          << (1 + 1 + 10 + 11 + 1))
18004ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              | (bI1         << (1 + 10 + 11 + 1))
18005ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              | (bI2         << (10 + 11 + 1))
18006ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              | (INSN0(9,0)  << (11 + 1))
18007ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              | (INSN1(10,0) << 1);
18008ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         simm25 = (simm25 << 7) >> 7;
18009ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
18010ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(0 == (guest_R15_curr_instr_notENC & 1));
18011ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         UInt dst = simm25 + guest_R15_curr_instr_notENC + 4;
18012ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
18013ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* If in an IT block, must be the last insn. */
18014ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         gen_SIGILL_T_if_in_but_NLI_ITBlock(old_itstate, new_itstate);
18015ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
18016ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         // go uncond
18017ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         mk_skip_over_T32_if_cond_is_false(condT);
18018ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         condT = IRTemp_INVALID;
18019ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         // now uncond
18020ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
18021ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         // branch to dst
18022663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         llPutIReg(15, mkU32( dst | 1 /*CPSR.T*/ ));
18023663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         dres.jk_StopHere = Ijk_Boring;
18024663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         dres.whatNext    = Dis_StopHere;
18025ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("b.w 0x%x\n", dst);
18026ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto decode_success;
18027ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
18028ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
18029ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
18030ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* ------------------ TBB, TBH ------------------ */
18031ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (INSN0(15,4) == 0xE8D && INSN1(15,5) == 0x780) {
18032ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt rN = INSN0(3,0);
18033ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt rM = INSN1(3,0);
18034ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt bH = INSN1(4,4);
18035ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (bH/*ATC*/ || (rN != 13 && !isBadRegT(rM))) {
18036ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Must be last or not-in IT block */
18037ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         gen_SIGILL_T_if_in_but_NLI_ITBlock(old_itstate, new_itstate);
18038ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Go uncond */
18039ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         mk_skip_over_T32_if_cond_is_false(condT);
18040ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         condT = IRTemp_INVALID;
18041ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
18042ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRExpr* ea
18043ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             = binop(Iop_Add32,
18044ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     getIRegT(rN),
18045ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     bH ? binop(Iop_Shl32, getIRegT(rM), mkU8(1))
18046ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        : getIRegT(rM));
18047ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
18048ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp delta = newTemp(Ity_I32);
18049ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (bH) {
18050ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            assign(delta, unop(Iop_16Uto32, loadLE(Ity_I16, ea)));
18051ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
18052ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            assign(delta, unop(Iop_8Uto32, loadLE(Ity_I8, ea)));
18053ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
18054ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
18055663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         llPutIReg(
18056663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            15,
18057663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            binop(Iop_Or32,
18058663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  binop(Iop_Add32,
18059663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                        getIRegT(15),
18060663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                        binop(Iop_Shl32, mkexpr(delta), mkU8(1))
18061663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  ),
18062663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  mkU32(1)
18063663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         ));
18064663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         dres.jk_StopHere = Ijk_Boring;
18065663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         dres.whatNext    = Dis_StopHere;
18066ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("tb%c [r%u, r%u%s]\n",
18067ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             bH ? 'h' : 'b', rN, rM, bH ? ", LSL #1" : "");
18068ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto decode_success;
18069ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
18070ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
18071ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
18072ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* ------------------ UBFX ------------------ */
18073ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* ------------------ SBFX ------------------ */
18074ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* There's also ARM versions of same, but it doesn't seem worth the
18075ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      hassle to common up the handling (it's only a couple of C
18076ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      statements). */
18077ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if ((INSN0(15,4) == 0xF3C // UBFX
18078ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        || INSN0(15,4) == 0xF34) // SBFX
18079ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && INSN1(15,15) == 0 && INSN1(5,5) == 0) {
18080ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt rN  = INSN0(3,0);
18081ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt rD  = INSN1(11,8);
18082ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt lsb = (INSN1(14,12) << 2) | INSN1(7,6);
18083ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt wm1 = INSN1(4,0);
18084ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt msb =  lsb + wm1;
18085ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (!isBadRegT(rD) && !isBadRegT(rN) && msb <= 31) {
18086ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         Bool   isU  = INSN0(15,4) == 0xF3C;
18087ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp src  = newTemp(Ity_I32);
18088ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp tmp  = newTemp(Ity_I32);
18089ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp res  = newTemp(Ity_I32);
18090ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         UInt   mask = ((1 << wm1) - 1) + (1 << wm1);
18091ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(msb >= 0 && msb <= 31);
18092ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(mask != 0); // guaranteed by msb being in 0 .. 31 inclusive
18093ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
18094ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign(src, getIRegT(rN));
18095ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign(tmp, binop(Iop_And32,
18096ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           binop(Iop_Shr32, mkexpr(src), mkU8(lsb)),
18097ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           mkU32(mask)));
18098ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign(res, binop(isU ? Iop_Shr32 : Iop_Sar32,
18099ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           binop(Iop_Shl32, mkexpr(tmp), mkU8(31-wm1)),
18100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           mkU8(31-wm1)));
18101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
18102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putIRegT(rD, mkexpr(res), condT);
18103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
18104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("%s r%u, r%u, #%u, #%u\n",
18105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             isU ? "ubfx" : "sbfx", rD, rN, lsb, wm1 + 1);
18106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto decode_success;
18107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
18108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
18109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
18110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* ------------------ UXTB ------------------ */
18111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* ------------------ UXTH ------------------ */
18112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* ------------------ SXTB ------------------ */
18113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* ------------------ SXTH ------------------ */
18114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* ----------------- UXTB16 ----------------- */
18115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* ----------------- SXTB16 ----------------- */
18116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* FIXME: this is an exact duplicate of the ARM version.  They
18117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      should be commoned up. */
18118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if ((INSN0(15,0) == 0xFA5F     // UXTB
18119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        || INSN0(15,0) == 0xFA1F  // UXTH
18120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        || INSN0(15,0) == 0xFA4F  // SXTB
18121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        || INSN0(15,0) == 0xFA0F  // SXTH
18122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        || INSN0(15,0) == 0xFA3F  // UXTB16
18123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        || INSN0(15,0) == 0xFA2F) // SXTB16
18124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && INSN1(15,12) == BITS4(1,1,1,1)
18125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && INSN1(7,6) == BITS2(1,0)) {
18126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt rD = INSN1(11,8);
18127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt rM = INSN1(3,0);
18128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt rot = INSN1(5,4);
18129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (!isBadRegT(rD) && !isBadRegT(rM)) {
18130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HChar* nm = "???";
18131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp srcT = newTemp(Ity_I32);
18132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp rotT = newTemp(Ity_I32);
18133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp dstT = newTemp(Ity_I32);
18134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign(srcT, getIRegT(rM));
18135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign(rotT, genROR32(srcT, 8 * rot));
18136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         switch (INSN0(15,0)) {
18137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 0xFA5F: // UXTB
18138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               nm = "uxtb";
18139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               assign(dstT, unop(Iop_8Uto32,
18140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                 unop(Iop_32to8, mkexpr(rotT))));
18141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
18142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 0xFA1F: // UXTH
18143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               nm = "uxth";
18144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               assign(dstT, unop(Iop_16Uto32,
18145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                 unop(Iop_32to16, mkexpr(rotT))));
18146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
18147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 0xFA4F: // SXTB
18148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               nm = "sxtb";
18149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               assign(dstT, unop(Iop_8Sto32,
18150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                 unop(Iop_32to8, mkexpr(rotT))));
18151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
18152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 0xFA0F: // SXTH
18153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               nm = "sxth";
18154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               assign(dstT, unop(Iop_16Sto32,
18155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                 unop(Iop_32to16, mkexpr(rotT))));
18156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
18157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 0xFA3F: // UXTB16
18158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               nm = "uxtb16";
18159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               assign(dstT, binop(Iop_And32, mkexpr(rotT),
18160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                             mkU32(0x00FF00FF)));
18161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
18162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 0xFA2F: { // SXTB16
18163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               nm = "sxtb16";
18164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               IRTemp lo32 = newTemp(Ity_I32);
18165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               IRTemp hi32 = newTemp(Ity_I32);
18166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               assign(lo32, binop(Iop_And32, mkexpr(rotT), mkU32(0xFF)));
18167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               assign(hi32, binop(Iop_Shr32, mkexpr(rotT), mkU8(16)));
18168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               assign(
18169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  dstT,
18170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  binop(Iop_Or32,
18171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        binop(Iop_And32,
18172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              unop(Iop_8Sto32,
18173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                   unop(Iop_32to8, mkexpr(lo32))),
18174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              mkU32(0xFFFF)),
18175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        binop(Iop_Shl32,
18176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              unop(Iop_8Sto32,
18177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                   unop(Iop_32to8, mkexpr(hi32))),
18178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              mkU8(16))
18179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               ));
18180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
18181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
18182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            default:
18183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               vassert(0);
18184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
18185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putIRegT(rD, mkexpr(dstT), condT);
18186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("%s r%u, r%u, ror #%u\n", nm, rD, rM, 8 * rot);
18187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto decode_success;
18188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
18189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
18190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
18191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* -------------- MUL.W Rd, Rn, Rm -------------- */
18192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (INSN0(15,4) == 0xFB0
18193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && (INSN1(15,0) & 0xF0F0) == 0xF000) {
18194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt rN = INSN0(3,0);
18195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt rD = INSN1(11,8);
18196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt rM = INSN1(3,0);
18197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (!isBadRegT(rD) && !isBadRegT(rN) && !isBadRegT(rM)) {
18198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp res = newTemp(Ity_I32);
18199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign(res, binop(Iop_Mul32, getIRegT(rN), getIRegT(rM)));
18200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putIRegT(rD, mkexpr(res), condT);
18201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("mul.w r%u, r%u, r%u\n", rD, rN, rM);
18202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto decode_success;
18203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
18204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
18205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
182066d67c5925dfb5eae9a15380403fa2a81e18a91eaBen Cheng   /* -------------- SDIV.W Rd, Rn, Rm -------------- */
182076d67c5925dfb5eae9a15380403fa2a81e18a91eaBen Cheng   if (INSN0(15,4) == 0xFB9
182086d67c5925dfb5eae9a15380403fa2a81e18a91eaBen Cheng       && (INSN1(15,0) & 0xF0F0) == 0xF0F0) {
182096d67c5925dfb5eae9a15380403fa2a81e18a91eaBen Cheng      UInt rN = INSN0(3,0);
182106d67c5925dfb5eae9a15380403fa2a81e18a91eaBen Cheng      UInt rD = INSN1(11,8);
182116d67c5925dfb5eae9a15380403fa2a81e18a91eaBen Cheng      UInt rM = INSN1(3,0);
182126d67c5925dfb5eae9a15380403fa2a81e18a91eaBen Cheng      if (!isBadRegT(rD) && !isBadRegT(rN) && !isBadRegT(rM)) {
182136d67c5925dfb5eae9a15380403fa2a81e18a91eaBen Cheng         IRTemp res = newTemp(Ity_I32);
182146d67c5925dfb5eae9a15380403fa2a81e18a91eaBen Cheng         IRTemp argL  = newTemp(Ity_I32);
182156d67c5925dfb5eae9a15380403fa2a81e18a91eaBen Cheng         IRTemp argR  = newTemp(Ity_I32);
182166d67c5925dfb5eae9a15380403fa2a81e18a91eaBen Cheng         assign(argL, getIRegT(rN));
182176d67c5925dfb5eae9a15380403fa2a81e18a91eaBen Cheng         assign(argR, getIRegT(rM));
182186d67c5925dfb5eae9a15380403fa2a81e18a91eaBen Cheng         assign(res, binop(Iop_DivS32, mkexpr(argL), mkexpr(argR)));
182196d67c5925dfb5eae9a15380403fa2a81e18a91eaBen Cheng         putIRegT(rD, mkexpr(res), condT);
182206d67c5925dfb5eae9a15380403fa2a81e18a91eaBen Cheng         DIP("sdiv.w r%u, r%u, r%u\n", rD, rN, rM);
182216d67c5925dfb5eae9a15380403fa2a81e18a91eaBen Cheng         goto decode_success;
182226d67c5925dfb5eae9a15380403fa2a81e18a91eaBen Cheng      }
182236d67c5925dfb5eae9a15380403fa2a81e18a91eaBen Cheng   }
182246d67c5925dfb5eae9a15380403fa2a81e18a91eaBen Cheng
182256d67c5925dfb5eae9a15380403fa2a81e18a91eaBen Cheng   /* -------------- UDIV.W Rd, Rn, Rm -------------- */
182266d67c5925dfb5eae9a15380403fa2a81e18a91eaBen Cheng   if (INSN0(15,4) == 0xFBB
182276d67c5925dfb5eae9a15380403fa2a81e18a91eaBen Cheng       && (INSN1(15,0) & 0xF0F0) == 0xF0F0) {
182286d67c5925dfb5eae9a15380403fa2a81e18a91eaBen Cheng      UInt rN = INSN0(3,0);
182296d67c5925dfb5eae9a15380403fa2a81e18a91eaBen Cheng      UInt rD = INSN1(11,8);
182306d67c5925dfb5eae9a15380403fa2a81e18a91eaBen Cheng      UInt rM = INSN1(3,0);
182316d67c5925dfb5eae9a15380403fa2a81e18a91eaBen Cheng      if (!isBadRegT(rD) && !isBadRegT(rN) && !isBadRegT(rM)) {
182326d67c5925dfb5eae9a15380403fa2a81e18a91eaBen Cheng         IRTemp res = newTemp(Ity_I32);
182336d67c5925dfb5eae9a15380403fa2a81e18a91eaBen Cheng         IRTemp argL  = newTemp(Ity_I32);
182346d67c5925dfb5eae9a15380403fa2a81e18a91eaBen Cheng         IRTemp argR  = newTemp(Ity_I32);
182356d67c5925dfb5eae9a15380403fa2a81e18a91eaBen Cheng         assign(argL, getIRegT(rN));
182366d67c5925dfb5eae9a15380403fa2a81e18a91eaBen Cheng         assign(argR, getIRegT(rM));
182376d67c5925dfb5eae9a15380403fa2a81e18a91eaBen Cheng         assign(res, binop(Iop_DivU32, mkexpr(argL), mkexpr(argR)));
182386d67c5925dfb5eae9a15380403fa2a81e18a91eaBen Cheng         putIRegT(rD, mkexpr(res), condT);
182396d67c5925dfb5eae9a15380403fa2a81e18a91eaBen Cheng         DIP("udiv.w r%u, r%u, r%u\n", rD, rN, rM);
182406d67c5925dfb5eae9a15380403fa2a81e18a91eaBen Cheng         goto decode_success;
182416d67c5925dfb5eae9a15380403fa2a81e18a91eaBen Cheng      }
182426d67c5925dfb5eae9a15380403fa2a81e18a91eaBen Cheng   }
182436d67c5925dfb5eae9a15380403fa2a81e18a91eaBen Cheng
18244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* ------------------ {U,S}MULL ------------------ */
18245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if ((INSN0(15,4) == 0xFB8 || INSN0(15,4) == 0xFBA)
18246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && INSN1(7,4) == BITS4(0,0,0,0)) {
18247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt isU  = INSN0(5,5);
18248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt rN   = INSN0(3,0);
18249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt rDlo = INSN1(15,12);
18250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt rDhi = INSN1(11,8);
18251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt rM   = INSN1(3,0);
18252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (!isBadRegT(rDhi) && !isBadRegT(rDlo)
18253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          && !isBadRegT(rN) && !isBadRegT(rM) && rDlo != rDhi) {
18254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp res   = newTemp(Ity_I64);
18255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign(res, binop(isU ? Iop_MullU32 : Iop_MullS32,
18256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           getIRegT(rN), getIRegT(rM)));
18257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putIRegT( rDhi, unop(Iop_64HIto32, mkexpr(res)), condT );
18258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putIRegT( rDlo, unop(Iop_64to32, mkexpr(res)), condT );
18259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("%cmull r%u, r%u, r%u, r%u\n",
18260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             isU ? 'u' : 's', rDlo, rDhi, rN, rM);
18261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto decode_success;
18262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
18263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
18264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
18265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* ------------------ ML{A,S} ------------------ */
18266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (INSN0(15,4) == 0xFB0
18267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && (   INSN1(7,4) == BITS4(0,0,0,0)    // MLA
18268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           || INSN1(7,4) == BITS4(0,0,0,1))) { // MLS
18269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt rN = INSN0(3,0);
18270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt rA = INSN1(15,12);
18271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt rD = INSN1(11,8);
18272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt rM = INSN1(3,0);
18273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (!isBadRegT(rD) && !isBadRegT(rN)
18274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          && !isBadRegT(rM) && !isBadRegT(rA)) {
18275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         Bool   isMLA = INSN1(7,4) == BITS4(0,0,0,0);
18276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp res   = newTemp(Ity_I32);
18277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign(res,
18278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                binop(isMLA ? Iop_Add32 : Iop_Sub32,
18279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      getIRegT(rA),
18280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      binop(Iop_Mul32, getIRegT(rN), getIRegT(rM))));
18281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putIRegT(rD, mkexpr(res), condT);
18282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("%s r%u, r%u, r%u, r%u\n",
18283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             isMLA ? "mla" : "mls", rD, rN, rM, rA);
18284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto decode_success;
18285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
18286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
18287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
18288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* ------------------ (T3) ADR ------------------ */
18289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if ((INSN0(15,0) == 0xF20F || INSN0(15,0) == 0xF60F)
18290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && INSN1(15,15) == 0) {
18291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* rD = align4(PC) + imm32 */
18292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt rD = INSN1(11,8);
18293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (!isBadRegT(rD)) {
18294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         UInt imm32 = (INSN0(10,10) << 11)
18295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      | (INSN1(14,12) << 8) | INSN1(7,0);
18296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putIRegT(rD, binop(Iop_Add32,
18297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            binop(Iop_And32, getIRegT(15), mkU32(~3U)),
18298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            mkU32(imm32)),
18299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      condT);
18300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("add r%u, pc, #%u\n", rD, imm32);
18301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto decode_success;
18302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
18303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
18304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
18305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* ----------------- (T1) UMLAL ----------------- */
18306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* ----------------- (T1) SMLAL ----------------- */
18307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if ((INSN0(15,4) == 0xFBE // UMLAL
18308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        || INSN0(15,4) == 0xFBC) // SMLAL
18309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && INSN1(7,4) == BITS4(0,0,0,0)) {
18310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt rN   = INSN0(3,0);
18311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt rDlo = INSN1(15,12);
18312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt rDhi = INSN1(11,8);
18313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt rM   = INSN1(3,0);
18314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (!isBadRegT(rDlo) && !isBadRegT(rDhi) && !isBadRegT(rN)
18315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          && !isBadRegT(rM) && rDhi != rDlo) {
18316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         Bool   isS   = INSN0(15,4) == 0xFBC;
18317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp argL  = newTemp(Ity_I32);
18318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp argR  = newTemp(Ity_I32);
18319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp old   = newTemp(Ity_I64);
18320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp res   = newTemp(Ity_I64);
18321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp resHi = newTemp(Ity_I32);
18322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp resLo = newTemp(Ity_I32);
18323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IROp   mulOp = isS ? Iop_MullS32 : Iop_MullU32;
18324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( argL, getIRegT(rM));
18325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( argR, getIRegT(rN));
18326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( old, binop(Iop_32HLto64, getIRegT(rDhi), getIRegT(rDlo)) );
18327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( res, binop(Iop_Add64,
18328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            mkexpr(old),
18329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            binop(mulOp, mkexpr(argL), mkexpr(argR))) );
18330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( resHi, unop(Iop_64HIto32, mkexpr(res)) );
18331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( resLo, unop(Iop_64to32, mkexpr(res)) );
18332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putIRegT( rDhi, mkexpr(resHi), condT );
18333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putIRegT( rDlo, mkexpr(resLo), condT );
18334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("%cmlal r%u, r%u, r%u, r%u\n",
18335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             isS ? 's' : 'u', rDlo, rDhi, rN, rM);
18336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto decode_success;
18337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
18338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
18339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
18340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* ------------------ (T2) ADR ------------------ */
18341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if ((INSN0(15,0) == 0xF2AF || INSN0(15,0) == 0xF6AF)
18342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && INSN1(15,15) == 0) {
18343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* rD = align4(PC) - imm32 */
18344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt rD = INSN1(11,8);
18345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (!isBadRegT(rD)) {
18346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         UInt imm32 = (INSN0(10,10) << 11)
18347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      | (INSN1(14,12) << 8) | INSN1(7,0);
18348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putIRegT(rD, binop(Iop_Sub32,
18349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            binop(Iop_And32, getIRegT(15), mkU32(~3U)),
18350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            mkU32(imm32)),
18351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      condT);
18352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("sub r%u, pc, #%u\n", rD, imm32);
18353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto decode_success;
18354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
18355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
18356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
18357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* ------------------- (T1) BFI ------------------- */
18358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* ------------------- (T1) BFC ------------------- */
18359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (INSN0(15,4) == 0xF36 && INSN1(15,15) == 0 && INSN1(5,5) == 0) {
18360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt rD  = INSN1(11,8);
18361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt rN  = INSN0(3,0);
18362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt msb = INSN1(4,0);
18363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt lsb = (INSN1(14,12) << 2) | INSN1(7,6);
18364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (isBadRegT(rD) || rN == 13 || msb < lsb) {
18365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* undecodable; fall through */
18366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else {
18367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp src    = newTemp(Ity_I32);
18368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp olddst = newTemp(Ity_I32);
18369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp newdst = newTemp(Ity_I32);
18370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         UInt   mask = 1 << (msb - lsb);
18371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         mask = (mask - 1) + mask;
18372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(mask != 0); // guaranteed by "msb < lsb" check above
18373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         mask <<= lsb;
18374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
18375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign(src, rN == 15 ? mkU32(0) : getIRegT(rN));
18376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign(olddst, getIRegT(rD));
18377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign(newdst,
18378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                binop(Iop_Or32,
18379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   binop(Iop_And32,
18380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         binop(Iop_Shl32, mkexpr(src), mkU8(lsb)),
18381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         mkU32(mask)),
18382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   binop(Iop_And32,
18383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         mkexpr(olddst),
18384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         mkU32(~mask)))
18385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               );
18386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
18387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putIRegT(rD, mkexpr(newdst), condT);
18388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
18389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (rN == 15) {
18390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            DIP("bfc r%u, #%u, #%u\n",
18391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                rD, lsb, msb-lsb+1);
18392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
18393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            DIP("bfi r%u, r%u, #%u, #%u\n",
18394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                rD, rN, lsb, msb-lsb+1);
18395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
18396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto decode_success;
18397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
18398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
18399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
18400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* ------------------- (T1) SXTAH ------------------- */
18401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* ------------------- (T1) UXTAH ------------------- */
18402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if ((INSN0(15,4) == 0xFA1      // UXTAH
18403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        || INSN0(15,4) == 0xFA0)  // SXTAH
18404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && INSN1(15,12) == BITS4(1,1,1,1)
18405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && INSN1(7,6) == BITS2(1,0)) {
18406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Bool isU = INSN0(15,4) == 0xFA1;
18407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt rN  = INSN0(3,0);
18408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt rD  = INSN1(11,8);
18409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt rM  = INSN1(3,0);
18410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt rot = INSN1(5,4);
18411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (!isBadRegT(rD) && !isBadRegT(rN) && !isBadRegT(rM)) {
18412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp srcL = newTemp(Ity_I32);
18413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp srcR = newTemp(Ity_I32);
18414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp res  = newTemp(Ity_I32);
18415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign(srcR, getIRegT(rM));
18416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign(srcL, getIRegT(rN));
18417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign(res,  binop(Iop_Add32,
18418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            mkexpr(srcL),
18419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            unop(isU ? Iop_16Uto32 : Iop_16Sto32,
18420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                 unop(Iop_32to16,
18421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                      genROR32(srcR, 8 * rot)))));
18422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putIRegT(rD, mkexpr(res), condT);
18423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("%cxtah r%u, r%u, r%u, ror #%u\n",
18424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             isU ? 'u' : 's', rD, rN, rM, rot);
18425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto decode_success;
18426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
18427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
18428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
18429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* ------------------- (T1) SXTAB ------------------- */
18430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* ------------------- (T1) UXTAB ------------------- */
18431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if ((INSN0(15,4) == 0xFA5      // UXTAB
18432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        || INSN0(15,4) == 0xFA4)  // SXTAB
18433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && INSN1(15,12) == BITS4(1,1,1,1)
18434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && INSN1(7,6) == BITS2(1,0)) {
18435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Bool isU = INSN0(15,4) == 0xFA5;
18436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt rN  = INSN0(3,0);
18437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt rD  = INSN1(11,8);
18438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt rM  = INSN1(3,0);
18439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt rot = INSN1(5,4);
18440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (!isBadRegT(rD) && !isBadRegT(rN) && !isBadRegT(rM)) {
18441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp srcL = newTemp(Ity_I32);
18442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp srcR = newTemp(Ity_I32);
18443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp res  = newTemp(Ity_I32);
18444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign(srcR, getIRegT(rM));
18445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign(srcL, getIRegT(rN));
18446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign(res,  binop(Iop_Add32,
18447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            mkexpr(srcL),
18448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            unop(isU ? Iop_8Uto32 : Iop_8Sto32,
18449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                 unop(Iop_32to8,
18450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                      genROR32(srcR, 8 * rot)))));
18451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putIRegT(rD, mkexpr(res), condT);
18452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("%cxtab r%u, r%u, r%u, ror #%u\n",
18453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             isU ? 'u' : 's', rD, rN, rM, rot);
18454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto decode_success;
18455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
18456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
18457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
18458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* ------------------- (T1) CLZ ------------------- */
18459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (INSN0(15,4) == 0xFAB
18460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && INSN1(15,12) == BITS4(1,1,1,1)
18461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && INSN1(7,4) == BITS4(1,0,0,0)) {
18462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt rM1 = INSN0(3,0);
18463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt rD  = INSN1(11,8);
18464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt rM2 = INSN1(3,0);
18465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (!isBadRegT(rD) && !isBadRegT(rM1) && rM1 == rM2) {
18466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp arg = newTemp(Ity_I32);
18467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp res = newTemp(Ity_I32);
18468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign(arg, getIRegT(rM1));
18469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign(res, IRExpr_Mux0X(
18470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        unop(Iop_1Uto8,binop(Iop_CmpEQ32,
18471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                             mkexpr(arg),
18472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                             mkU32(0))),
18473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        unop(Iop_Clz32, mkexpr(arg)),
18474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        mkU32(32)
18475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ));
18476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putIRegT(rD, mkexpr(res), condT);
18477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("clz r%u, r%u\n", rD, rM1);
18478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto decode_success;
18479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
18480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
18481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
18482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* ------------------- (T1) RBIT ------------------- */
18483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (INSN0(15,4) == 0xFA9
18484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && INSN1(15,12) == BITS4(1,1,1,1)
18485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && INSN1(7,4) == BITS4(1,0,1,0)) {
18486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt rM1 = INSN0(3,0);
18487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt rD  = INSN1(11,8);
18488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt rM2 = INSN1(3,0);
18489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (!isBadRegT(rD) && !isBadRegT(rM1) && rM1 == rM2) {
18490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp arg = newTemp(Ity_I32);
18491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign(arg, getIRegT(rM1));
18492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp res = gen_BITREV(arg);
18493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putIRegT(rD, mkexpr(res), condT);
18494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("rbit r%u, r%u\n", rD, rM1);
18495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto decode_success;
18496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
18497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
18498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
18499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* ------------------- (T2) REV   ------------------- */
18500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* ------------------- (T2) REV16 ------------------- */
18501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (INSN0(15,4) == 0xFA9
18502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && INSN1(15,12) == BITS4(1,1,1,1)
18503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && (   INSN1(7,4) == BITS4(1,0,0,0)     // REV
18504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           || INSN1(7,4) == BITS4(1,0,0,1))) { // REV16
18505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt rM1   = INSN0(3,0);
18506ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt rD    = INSN1(11,8);
18507ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt rM2   = INSN1(3,0);
18508ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Bool isREV = INSN1(7,4) == BITS4(1,0,0,0);
18509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (!isBadRegT(rD) && !isBadRegT(rM1) && rM1 == rM2) {
18510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp arg = newTemp(Ity_I32);
18511ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign(arg, getIRegT(rM1));
18512ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp res = isREV ? gen_REV(arg) : gen_REV16(arg);
18513ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putIRegT(rD, mkexpr(res), condT);
18514ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("rev%s r%u, r%u\n", isREV ? "" : "16", rD, rM1);
18515ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto decode_success;
18516ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
18517ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
18518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
18519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* -------------- (T1) MSR apsr, reg -------------- */
18520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (INSN0(15,4) == 0xF38
18521ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && INSN1(15,12) == BITS4(1,0,0,0) && INSN1(9,0) == 0x000) {
18522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt rN          = INSN0(3,0);
18523ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt write_ge    = INSN1(10,10);
18524ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt write_nzcvq = INSN1(11,11);
18525ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (!isBadRegT(rN) && (write_nzcvq || write_ge)) {
18526ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp rNt = newTemp(Ity_I32);
18527ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign(rNt, getIRegT(rN));
18528ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         desynthesise_APSR( write_nzcvq, write_ge, rNt, condT );
18529ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("msr cpsr_%s%s, r%u\n",
18530ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             write_nzcvq ? "f" : "", write_ge ? "g" : "", rN);
18531ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto decode_success;
18532ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
18533ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
18534ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
18535ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* -------------- (T1) MRS reg, apsr -------------- */
18536ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (INSN0(15,0) == 0xF3EF
18537ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && INSN1(15,12) == BITS4(1,0,0,0) && INSN1(7,0) == 0x00) {
18538ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt rD = INSN1(11,8);
18539ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (!isBadRegT(rD)) {
18540ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp apsr = synthesise_APSR();
18541ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putIRegT( rD, mkexpr(apsr), condT );
18542ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("mrs r%u, cpsr\n", rD);
18543ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto decode_success;
18544ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
18545ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
18546ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
18547ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* ----------------- (T1) LDREX ----------------- */
18548ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (INSN0(15,4) == 0xE85 && INSN1(11,8) == BITS4(1,1,1,1)) {
18549ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt rN   = INSN0(3,0);
18550ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt rT   = INSN1(15,12);
18551ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt imm8 = INSN1(7,0);
18552ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (!isBadRegT(rT) && rN != 15) {
18553ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp res;
18554ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         // go uncond
18555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         mk_skip_over_T32_if_cond_is_false( condT );
18556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         // now uncond
18557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         res = newTemp(Ity_I32);
18558ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         stmt( IRStmt_LLSC(Iend_LE,
18559ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           res,
18560ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           binop(Iop_Add32, getIRegT(rN), mkU32(imm8 * 4)),
18561ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           NULL/*this is a load*/ ));
18562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putIRegT(rT, mkexpr(res), IRTemp_INVALID);
18563ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("ldrex r%u, [r%u, #+%u]\n", rT, rN, imm8 * 4);
18564ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto decode_success;
18565ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
18566ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
18567ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
18568b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   /* --------------- (T1) LDREX{B,H} --------------- */
18569b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   if (INSN0(15,4) == 0xE8D
18570b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov       && (INSN1(11,0) == 0xF4F || INSN1(11,0) == 0xF5F)) {
18571b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      UInt rN  = INSN0(3,0);
18572b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      UInt rT  = INSN1(15,12);
18573b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      Bool isH = INSN1(11,0) == 0xF5F;
18574b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      if (!isBadRegT(rT) && rN != 15) {
18575b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         IRTemp res;
18576b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         // go uncond
18577b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         mk_skip_over_T32_if_cond_is_false( condT );
18578b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         // now uncond
18579b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         res = newTemp(isH ? Ity_I16 : Ity_I8);
18580b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         stmt( IRStmt_LLSC(Iend_LE, res, getIRegT(rN),
18581b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                           NULL/*this is a load*/ ));
18582b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         putIRegT(rT, unop(isH ? Iop_16Uto32 : Iop_8Uto32, mkexpr(res)),
18583b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                      IRTemp_INVALID);
18584b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         DIP("ldrex%c r%u, [r%u]\n", isH ? 'h' : 'b', rT, rN);
18585b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         goto decode_success;
18586b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      }
18587b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   }
18588b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
18589b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   /* --------------- (T1) LDREXD --------------- */
18590b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   if (INSN0(15,4) == 0xE8D && INSN1(7,0) == 0x7F) {
18591b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      UInt rN  = INSN0(3,0);
18592b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      UInt rT  = INSN1(15,12);
18593b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      UInt rT2 = INSN1(11,8);
18594b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      if (!isBadRegT(rT) && !isBadRegT(rT2) && rT != rT2 && rN != 15) {
18595b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         IRTemp res;
18596b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         // go uncond
18597b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         mk_skip_over_T32_if_cond_is_false( condT );
18598b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         // now uncond
18599b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         res = newTemp(Ity_I64);
18600b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         // FIXME: assumes little-endian guest
18601b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         stmt( IRStmt_LLSC(Iend_LE, res, getIRegT(rN),
18602b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                           NULL/*this is a load*/ ));
18603b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         // FIXME: assumes little-endian guest
18604b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         putIRegT(rT,  unop(Iop_64to32,   mkexpr(res)), IRTemp_INVALID);
18605b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         putIRegT(rT2, unop(Iop_64HIto32, mkexpr(res)), IRTemp_INVALID);
18606b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         DIP("ldrexd r%u, r%u, [r%u]\n", rT, rT2, rN);
18607b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         goto decode_success;
18608b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      }
18609b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   }
18610b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
18611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* ----------------- (T1) STREX ----------------- */
18612ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (INSN0(15,4) == 0xE84) {
18613ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt rN   = INSN0(3,0);
18614ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt rT   = INSN1(15,12);
18615ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt rD   = INSN1(11,8);
18616ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt imm8 = INSN1(7,0);
18617ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (!isBadRegT(rD) && !isBadRegT(rT) && rN != 15
18618ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          && rD != rN && rD != rT) {
18619ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp resSC1, resSC32;
18620ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         // go uncond
18621ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         mk_skip_over_T32_if_cond_is_false( condT );
18622ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         // now uncond
18623ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Ok, now we're unconditional.  Do the store. */
18624ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         resSC1 = newTemp(Ity_I1);
18625ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         stmt( IRStmt_LLSC(Iend_LE,
18626ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           resSC1,
18627ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           binop(Iop_Add32, getIRegT(rN), mkU32(imm8 * 4)),
18628ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           getIRegT(rT)) );
18629ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Set rD to 1 on failure, 0 on success.  Currently we have
18630ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            resSC1 == 0 on failure, 1 on success. */
18631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         resSC32 = newTemp(Ity_I32);
18632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign(resSC32,
18633ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                unop(Iop_1Uto32, unop(Iop_Not1, mkexpr(resSC1))));
18634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putIRegT(rD, mkexpr(resSC32), IRTemp_INVALID);
18635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("strex r%u, r%u, [r%u, #+%u]\n", rD, rT, rN, imm8 * 4);
18636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto decode_success;
18637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
18638ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
18639ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
18640b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   /* --------------- (T1) STREX{B,H} --------------- */
18641b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   if (INSN0(15,4) == 0xE8C
18642b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov       && (INSN1(11,4) == 0xF4 || INSN1(11,4) == 0xF5)) {
18643b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      UInt rN  = INSN0(3,0);
18644b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      UInt rT  = INSN1(15,12);
18645b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      UInt rD  = INSN1(3,0);
18646b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      Bool isH = INSN1(11,4) == 0xF5;
18647b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      if (!isBadRegT(rD) && !isBadRegT(rT) && rN != 15
18648b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov          && rD != rN && rD != rT) {
18649b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         IRTemp resSC1, resSC32;
18650b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         // go uncond
18651b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         mk_skip_over_T32_if_cond_is_false( condT );
18652b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         // now uncond
18653b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         /* Ok, now we're unconditional.  Do the store. */
18654b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         resSC1 = newTemp(Ity_I1);
18655b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         stmt( IRStmt_LLSC(Iend_LE, resSC1, getIRegT(rN),
18656b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                           unop(isH ? Iop_32to16 : Iop_32to8,
18657b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                getIRegT(rT))) );
18658b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         /* Set rD to 1 on failure, 0 on success.  Currently we have
18659b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            resSC1 == 0 on failure, 1 on success. */
18660b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         resSC32 = newTemp(Ity_I32);
18661b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         assign(resSC32,
18662b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                unop(Iop_1Uto32, unop(Iop_Not1, mkexpr(resSC1))));
18663b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         putIRegT(rD, mkexpr(resSC32), IRTemp_INVALID);
18664b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         DIP("strex%c r%u, r%u, [r%u]\n", isH ? 'h' : 'b', rD, rT, rN);
186651b891657a2208341cc71c68ae16eada0bee46d91Jeff Brown         goto decode_success;
186661b891657a2208341cc71c68ae16eada0bee46d91Jeff Brown      }
186671b891657a2208341cc71c68ae16eada0bee46d91Jeff Brown   }
186681b891657a2208341cc71c68ae16eada0bee46d91Jeff Brown
18669b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   /* ---------------- (T1) STREXD ---------------- */
18670b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   if (INSN0(15,4) == 0xE8C && INSN1(7,4) == BITS4(0,1,1,1)) {
18671b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      UInt rN  = INSN0(3,0);
18672b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      UInt rT  = INSN1(15,12);
18673b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      UInt rT2 = INSN1(11,8);
18674b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      UInt rD  = INSN1(3,0);
18675b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      if (!isBadRegT(rD) && !isBadRegT(rT) && !isBadRegT(rT2)
18676b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov          && rN != 15 && rD != rN && rD != rT && rD != rT) {
18677b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         IRTemp resSC1, resSC32, data;
18678b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         // go uncond
18679b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         mk_skip_over_T32_if_cond_is_false( condT );
18680b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         // now uncond
18681b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         /* Ok, now we're unconditional.  Do the store. */
18682b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         resSC1 = newTemp(Ity_I1);
18683b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         data = newTemp(Ity_I64);
18684b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         // FIXME: assumes little-endian guest
18685b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         assign(data, binop(Iop_32HLto64, getIRegT(rT2), getIRegT(rT)));
18686b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         // FIXME: assumes little-endian guest
18687b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         stmt( IRStmt_LLSC(Iend_LE, resSC1, getIRegT(rN), mkexpr(data)));
18688b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         /* Set rD to 1 on failure, 0 on success.  Currently we have
18689b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            resSC1 == 0 on failure, 1 on success. */
18690b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         resSC32 = newTemp(Ity_I32);
18691b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         assign(resSC32,
18692b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                unop(Iop_1Uto32, unop(Iop_Not1, mkexpr(resSC1))));
18693b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         putIRegT(rD, mkexpr(resSC32), IRTemp_INVALID);
18694b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         DIP("strexd r%u, r%u, r%u, [r%u]\n", rD, rT, rT2, rN);
18695b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         goto decode_success;
18696b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      }
18697b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   }
18698ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* -------------- v7 barrier insns -------------- */
18699545813738cad7083ce736912c82ad4587cbce489Jeff Brown   if (INSN0(15,0) == 0xF3BF && (INSN1(15,0) & 0xFF00) == 0x8F00) {
18700b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      /* FIXME: should this be unconditional? */
18701ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* XXX this isn't really right, is it?  The generated IR does
18702ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         them unconditionally.  I guess it doesn't matter since it
18703ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         doesn't do any harm to do them even when the guarding
18704ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         condition is false -- it's just a performance loss. */
18705545813738cad7083ce736912c82ad4587cbce489Jeff Brown      switch (INSN1(7,0)) {
18706545813738cad7083ce736912c82ad4587cbce489Jeff Brown         case 0x4F: /* DSB sy */
18707545813738cad7083ce736912c82ad4587cbce489Jeff Brown         case 0x4E: /* DSB st */
18708545813738cad7083ce736912c82ad4587cbce489Jeff Brown         case 0x4B: /* DSB ish */
18709545813738cad7083ce736912c82ad4587cbce489Jeff Brown         case 0x4A: /* DSB ishst */
18710545813738cad7083ce736912c82ad4587cbce489Jeff Brown         case 0x47: /* DSB nsh */
18711545813738cad7083ce736912c82ad4587cbce489Jeff Brown         case 0x46: /* DSB nshst */
18712545813738cad7083ce736912c82ad4587cbce489Jeff Brown         case 0x43: /* DSB osh */
18713545813738cad7083ce736912c82ad4587cbce489Jeff Brown         case 0x42: /* DSB oshst */
18714ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            stmt( IRStmt_MBE(Imbe_Fence) );
18715ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            DIP("DSB\n");
18716ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto decode_success;
18717545813738cad7083ce736912c82ad4587cbce489Jeff Brown         case 0x5F: /* DMB sy */
18718545813738cad7083ce736912c82ad4587cbce489Jeff Brown         case 0x5E: /* DMB st */
18719545813738cad7083ce736912c82ad4587cbce489Jeff Brown         case 0x5B: /* DMB ish */
18720545813738cad7083ce736912c82ad4587cbce489Jeff Brown         case 0x5A: /* DMB ishst */
18721545813738cad7083ce736912c82ad4587cbce489Jeff Brown         case 0x57: /* DMB nsh */
18722545813738cad7083ce736912c82ad4587cbce489Jeff Brown         case 0x56: /* DMB nshst */
18723545813738cad7083ce736912c82ad4587cbce489Jeff Brown         case 0x53: /* DMB osh */
18724545813738cad7083ce736912c82ad4587cbce489Jeff Brown         case 0x52: /* DMB oshst */
18725ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            stmt( IRStmt_MBE(Imbe_Fence) );
18726ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            DIP("DMB\n");
18727ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto decode_success;
18728545813738cad7083ce736912c82ad4587cbce489Jeff Brown         case 0x6F: /* ISB */
18729ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            stmt( IRStmt_MBE(Imbe_Fence) );
18730ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            DIP("ISB\n");
18731ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto decode_success;
18732ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         default:
18733ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
18734ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
18735ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
18736ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
18737b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   /* ---------------------- PLD{,W} ---------------------- */
18738b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   if ((INSN0(15,4) & 0xFFD) == 0xF89 && INSN1(15,12) == 0xF) {
18739b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      /* FIXME: should this be unconditional? */
18740b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      /* PLD/PLDW immediate, encoding T1 */
18741b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      UInt rN    = INSN0(3,0);
18742b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      UInt bW    = INSN0(5,5);
18743b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      UInt imm12 = INSN1(11,0);
18744b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      DIP("pld%s [r%u, #%u]\n", bW ? "w" : "",  rN, imm12);
18745b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      goto decode_success;
18746b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   }
18747b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
18748b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   if ((INSN0(15,4) & 0xFFD) == 0xF81 && INSN1(15,8) == 0xFC) {
18749b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      /* FIXME: should this be unconditional? */
18750b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      /* PLD/PLDW immediate, encoding T2 */
18751b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      UInt rN    = INSN0(3,0);
18752b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      UInt bW    = INSN0(5,5);
18753b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      UInt imm8  = INSN1(7,0);
18754b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      DIP("pld%s [r%u, #-%u]\n", bW ? "w" : "",  rN, imm8);
18755b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      goto decode_success;
18756b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   }
18757b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
18758b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   if ((INSN0(15,4) & 0xFFD) == 0xF81 && INSN1(15,6) == 0x3C0) {
18759b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      /* FIXME: should this be unconditional? */
18760b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      /* PLD/PLDW register, encoding T1 */
18761b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      UInt rN   = INSN0(3,0);
18762b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      UInt rM   = INSN1(3,0);
18763b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      UInt bW   = INSN0(5,5);
18764b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      UInt imm2 = INSN1(5,4);
18765b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      if (!isBadRegT(rM)) {
18766b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         DIP("pld%s [r%u, r%u, lsl %d]\n", bW ? "w" : "", rN, rM, imm2);
18767b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         goto decode_success;
18768b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      }
18769b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      /* fall through */
18770b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   }
18771b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
18772f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root   /* -------------- read CP15 TPIDRURO register ------------- */
18773f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root   /* mrc     p15, 0,  r0, c13, c0, 3  up to
18774f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root      mrc     p15, 0, r14, c13, c0, 3
18775f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root   */
18776f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root   /* I don't know whether this is really v7-only.  But anyway, we
18777f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root      have to support it since arm-linux uses TPIDRURO as a thread
18778f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root      state register. */
18779f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root   if ((INSN0(15,0) == 0xEE1D) && (INSN1(11,0) == 0x0F70)) {
18780b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      /* FIXME: should this be unconditional? */
18781f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root      UInt rD = INSN1(15,12);
18782f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root      if (!isBadRegT(rD)) {
18783f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root         putIRegT(rD, IRExpr_Get(OFFB_TPIDRURO, Ity_I32), IRTemp_INVALID);
18784f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root         DIP("mrc p15,0, r%u, c13, c0, 3\n", rD);
18785f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root         goto decode_success;
18786f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root      }
18787f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root      /* fall through */
18788f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root   }
18789f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root
18790b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   /* ------------------- CLREX ------------------ */
18791b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   if (INSN0(15,0) == 0xF3BF && INSN1(15,0) == 0x8F2F) {
18792b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      /* AFAICS, this simply cancels a (all?) reservations made by a
18793b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         (any?) preceding LDREX(es).  Arrange to hand it through to
18794b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         the back end. */
18795b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      mk_skip_over_T32_if_cond_is_false( condT );
18796b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      stmt( IRStmt_MBE(Imbe_CancelReservation) );
18797b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      DIP("clrex\n");
18798b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      goto decode_success;
18799b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   }
18800b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
18801ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* ------------------- NOP ------------------ */
18802ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (INSN0(15,0) == 0xF3AF && INSN1(15,0) == 0x8000) {
18803ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("nop\n");
18804ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      goto decode_success;
18805ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
18806ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
18807663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* ------------------- (T1) SMMUL{R} ------------------ */
18808663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (INSN0(15,7) == BITS9(1,1,1,1,1,0,1,1,0)
18809663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng       && INSN0(6,4) == BITS3(1,0,1)
18810663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng       && INSN1(15,12) == BITS4(1,1,1,1)
18811663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng       && INSN1(7,5) == BITS3(0,0,0)) {
18812663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      UInt bitR = INSN1(4,4);
18813663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      UInt rD = INSN1(11,8);
18814663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      UInt rM = INSN1(3,0);
18815663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      UInt rN = INSN0(3,0);
18816663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (!isBadRegT(rD) && !isBadRegT(rN) && !isBadRegT(rM)) {
18817663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         IRExpr* res
18818663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         = unop(Iop_64HIto32,
18819663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                binop(Iop_Add64,
18820663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                      binop(Iop_MullS32, getIRegT(rN), getIRegT(rM)),
18821663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                      mkU64(bitR ? 0x80000000ULL : 0ULL)));
18822663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         putIRegT(rD, res, condT);
18823663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         DIP("smmul%s r%u, r%u, r%u\n",
18824663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng             bitR ? "r" : "", rD, rN, rM);
18825663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         goto decode_success;
18826663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
18827663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
18828663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
18829ccebb1bf6bf864caa46e59c81eacab38e2dc299eBen Cheng   /* ------------------- (T1) SMMLA{R} ------------------ */
18830ccebb1bf6bf864caa46e59c81eacab38e2dc299eBen Cheng   if (INSN0(15,7) == BITS9(1,1,1,1,1,0,1,1,0)
18831ccebb1bf6bf864caa46e59c81eacab38e2dc299eBen Cheng       && INSN0(6,4) == BITS3(1,0,1)
18832ccebb1bf6bf864caa46e59c81eacab38e2dc299eBen Cheng       && INSN1(7,5) == BITS3(0,0,0)) {
18833ccebb1bf6bf864caa46e59c81eacab38e2dc299eBen Cheng      UInt bitR = INSN1(4,4);
18834ccebb1bf6bf864caa46e59c81eacab38e2dc299eBen Cheng      UInt rA = INSN1(15,12);
18835ccebb1bf6bf864caa46e59c81eacab38e2dc299eBen Cheng      UInt rD = INSN1(11,8);
18836ccebb1bf6bf864caa46e59c81eacab38e2dc299eBen Cheng      UInt rM = INSN1(3,0);
18837ccebb1bf6bf864caa46e59c81eacab38e2dc299eBen Cheng      UInt rN = INSN0(3,0);
18838ccebb1bf6bf864caa46e59c81eacab38e2dc299eBen Cheng      if (!isBadRegT(rD) && !isBadRegT(rN) && !isBadRegT(rM) && (rA != 13)) {
18839ccebb1bf6bf864caa46e59c81eacab38e2dc299eBen Cheng         IRExpr* res
18840ccebb1bf6bf864caa46e59c81eacab38e2dc299eBen Cheng         = unop(Iop_64HIto32,
18841ccebb1bf6bf864caa46e59c81eacab38e2dc299eBen Cheng                binop(Iop_Add64,
18842ccebb1bf6bf864caa46e59c81eacab38e2dc299eBen Cheng                      binop(Iop_Add64,
18843ccebb1bf6bf864caa46e59c81eacab38e2dc299eBen Cheng                            binop(Iop_32HLto64, getIRegT(rA), mkU32(0)),
18844ccebb1bf6bf864caa46e59c81eacab38e2dc299eBen Cheng                            binop(Iop_MullS32, getIRegT(rN), getIRegT(rM))),
18845ccebb1bf6bf864caa46e59c81eacab38e2dc299eBen Cheng                      mkU64(bitR ? 0x80000000ULL : 0ULL)));
18846ccebb1bf6bf864caa46e59c81eacab38e2dc299eBen Cheng         putIRegT(rD, res, condT);
18847ccebb1bf6bf864caa46e59c81eacab38e2dc299eBen Cheng         DIP("smmla%s r%u, r%u, r%u, r%u\n",
18848ccebb1bf6bf864caa46e59c81eacab38e2dc299eBen Cheng             bitR ? "r" : "", rD, rN, rM, rA);
18849ccebb1bf6bf864caa46e59c81eacab38e2dc299eBen Cheng         goto decode_success;
18850ccebb1bf6bf864caa46e59c81eacab38e2dc299eBen Cheng      }
18851ccebb1bf6bf864caa46e59c81eacab38e2dc299eBen Cheng   }
18852ccebb1bf6bf864caa46e59c81eacab38e2dc299eBen Cheng
18853ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* ----------------------------------------------------------- */
18854ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* -- VFP (CP 10, CP 11) instructions (in Thumb mode)       -- */
18855ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* ----------------------------------------------------------- */
18856ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
18857ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (INSN0(15,12) == BITS4(1,1,1,0)) {
18858ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt insn28 = (INSN0(11,0) << 16) | INSN1(15,0);
18859ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Bool ok_vfp = decode_CP10_CP11_instruction (
18860ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       &dres, insn28, condT, ARMCondAL/*bogus*/,
18861ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       True/*isT*/
18862ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    );
18863ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (ok_vfp)
18864ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto decode_success;
18865ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
18866ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
18867ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* ----------------------------------------------------------- */
18868ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* -- NEON instructions (in Thumb mode)                     -- */
18869ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* ----------------------------------------------------------- */
18870ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
18871ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (archinfo->hwcaps & VEX_HWCAPS_ARM_NEON) {
18872ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt insn32 = (INSN0(15,0) << 16) | INSN1(15,0);
18873ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Bool ok_neon = decode_NEON_instruction(
18874ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        &dres, insn32, condT, True/*isT*/
18875ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     );
18876ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (ok_neon)
18877ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto decode_success;
18878ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
18879ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
18880ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* ----------------------------------------------------------- */
18881ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* -- v6 media instructions (in Thumb mode)                 -- */
18882ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* ----------------------------------------------------------- */
18883ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
18884ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   { UInt insn32 = (INSN0(15,0) << 16) | INSN1(15,0);
18885ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     Bool ok_v6m = decode_V6MEDIA_instruction(
18886ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      &dres, insn32, condT, ARMCondAL/*bogus*/,
18887ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      True/*isT*/
18888ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   );
18889ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     if (ok_v6m)
18890ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        goto decode_success;
18891ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
18892ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
18893ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* ----------------------------------------------------------- */
18894ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* -- Undecodable                                           -- */
18895ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* ----------------------------------------------------------- */
18896ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
18897ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   goto decode_failure;
18898ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /*NOTREACHED*/
18899ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
18900ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  decode_failure:
18901ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* All decode failures end up here. */
18902ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vex_printf("disInstr(thumb): unhandled instruction: "
18903ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              "0x%04x 0x%04x\n", (UInt)insn0, (UInt)insn1);
18904ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
18905ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Back up ITSTATE to the initial value for this instruction.
18906ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      If we don't do that, any subsequent restart of the instruction
18907ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      will restart with the wrong value. */
18908663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (old_itstate != IRTemp_INVALID)
18909663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      put_ITSTATE(old_itstate);
18910663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
18911ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Tell the dispatcher that this insn cannot be decoded, and so has
18912ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      not been executed, and (is currently) the next to be executed.
18913ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      R15 should be up-to-date since it made so at the start of each
18914ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      insn, but nevertheless be paranoid and update it again right
18915ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      now. */
18916ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(0 == (guest_R15_curr_instr_notENC & 1));
18917ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   llPutIReg( 15, mkU32(guest_R15_curr_instr_notENC | 1) );
18918663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   dres.whatNext    = Dis_StopHere;
18919663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   dres.jk_StopHere = Ijk_NoDecode;
18920663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   dres.len         = 0;
18921ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return dres;
18922ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
18923ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  decode_success:
18924ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* All decode successes end up here. */
18925663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   vassert(dres.len == 4 || dres.len == 2 || dres.len == 20);
18926663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   switch (dres.whatNext) {
18927663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Dis_Continue:
18928663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         llPutIReg(15, mkU32(dres.len + (guest_R15_curr_instr_notENC | 1)));
18929663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         break;
18930663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Dis_ResteerU:
18931663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Dis_ResteerC:
18932663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         llPutIReg(15, mkU32(dres.continueAt));
18933663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         break;
18934663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      case Dis_StopHere:
18935663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         break;
18936663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      default:
18937663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         vassert(0);
18938ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
18939663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
18940663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   DIP("\n");
18941ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
18942ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return dres;
18943ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
18944ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  undef INSN0
18945ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  undef INSN1
18946ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
18947ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
18948ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#undef DIP
18949ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#undef DIS
18950ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
18951ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
18952b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/* Helper table for figuring out how many insns an IT insn
18953b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   conditionalises.
18954b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
18955b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   An ITxyz instruction of the format "1011 1111 firstcond mask"
18956b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   conditionalises some number of instructions, as indicated by the
18957b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   following table.  A value of zero indicates the instruction is
18958b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   invalid in some way.
18959b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
18960b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   mask = 0 means this isn't an IT instruction
18961b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   fc = 15 (NV) means unpredictable
18962b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
18963b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   The line fc = 14 (AL) is different from the others; there are
18964b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   additional constraints in this case.
18965b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
18966b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov          mask(0 ..                   15)
18967b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        +--------------------------------
18968b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   fc(0 | 0 4 3 4 2 4 3 4 1 4 3 4 2 4 3 4
18969b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   ..   | 0 4 3 4 2 4 3 4 1 4 3 4 2 4 3 4
18970b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        | 0 4 3 4 2 4 3 4 1 4 3 4 2 4 3 4
18971b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        | 0 4 3 4 2 4 3 4 1 4 3 4 2 4 3 4
18972b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        | 0 4 3 4 2 4 3 4 1 4 3 4 2 4 3 4
18973b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        | 0 4 3 4 2 4 3 4 1 4 3 4 2 4 3 4
18974b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        | 0 4 3 4 2 4 3 4 1 4 3 4 2 4 3 4
18975b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        | 0 4 3 4 2 4 3 4 1 4 3 4 2 4 3 4
18976b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        | 0 4 3 4 2 4 3 4 1 4 3 4 2 4 3 4
18977b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        | 0 4 3 4 2 4 3 4 1 4 3 4 2 4 3 4
18978b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        | 0 4 3 4 2 4 3 4 1 4 3 4 2 4 3 4
18979b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        | 0 4 3 4 2 4 3 4 1 4 3 4 2 4 3 4
18980b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        | 0 4 3 4 2 4 3 4 1 4 3 4 2 4 3 4
18981b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        | 0 4 3 4 2 4 3 4 1 4 3 4 2 4 3 4
18982b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        | 0 4 3 0 2 0 0 0 1 0 0 0 0 0 0 0
18983b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   15)  | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
18984b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
18985b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   To be conservative with the analysis, let's rule out the mask = 0
18986b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   case, since that isn't an IT insn at all.  But for all the other
18987b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   cases where the table contains zero, that means unpredictable, so
18988b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   let's say 4 to be conservative.  Hence we have a safe value for any
18989b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   IT (mask,fc) pair that the CPU would actually identify as an IT
18990b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   instruction.  The final table is
18991b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
18992b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov          mask(0 ..                   15)
18993b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        +--------------------------------
18994b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   fc(0 | 0 4 3 4 2 4 3 4 1 4 3 4 2 4 3 4
18995b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   ..   | 0 4 3 4 2 4 3 4 1 4 3 4 2 4 3 4
18996b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        | 0 4 3 4 2 4 3 4 1 4 3 4 2 4 3 4
18997b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        | 0 4 3 4 2 4 3 4 1 4 3 4 2 4 3 4
18998b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        | 0 4 3 4 2 4 3 4 1 4 3 4 2 4 3 4
18999b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        | 0 4 3 4 2 4 3 4 1 4 3 4 2 4 3 4
19000b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        | 0 4 3 4 2 4 3 4 1 4 3 4 2 4 3 4
19001b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        | 0 4 3 4 2 4 3 4 1 4 3 4 2 4 3 4
19002b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        | 0 4 3 4 2 4 3 4 1 4 3 4 2 4 3 4
19003b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        | 0 4 3 4 2 4 3 4 1 4 3 4 2 4 3 4
19004b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        | 0 4 3 4 2 4 3 4 1 4 3 4 2 4 3 4
19005b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        | 0 4 3 4 2 4 3 4 1 4 3 4 2 4 3 4
19006b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        | 0 4 3 4 2 4 3 4 1 4 3 4 2 4 3 4
19007b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        | 0 4 3 4 2 4 3 4 1 4 3 4 2 4 3 4
19008b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        | 0 4 3 4 2 4 4 4 1 4 4 4 4 4 4 4
19009b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   15)  | 0 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4
19010b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov*/
19011b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic const UChar it_length_table[256]
19012b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   = { 0, 4, 3, 4, 2, 4, 3, 4, 1, 4, 3, 4, 2, 4, 3, 4,
19013b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov       0, 4, 3, 4, 2, 4, 3, 4, 1, 4, 3, 4, 2, 4, 3, 4,
19014b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov       0, 4, 3, 4, 2, 4, 3, 4, 1, 4, 3, 4, 2, 4, 3, 4,
19015b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov       0, 4, 3, 4, 2, 4, 3, 4, 1, 4, 3, 4, 2, 4, 3, 4,
19016b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov       0, 4, 3, 4, 2, 4, 3, 4, 1, 4, 3, 4, 2, 4, 3, 4,
19017b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov       0, 4, 3, 4, 2, 4, 3, 4, 1, 4, 3, 4, 2, 4, 3, 4,
19018b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov       0, 4, 3, 4, 2, 4, 3, 4, 1, 4, 3, 4, 2, 4, 3, 4,
19019b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov       0, 4, 3, 4, 2, 4, 3, 4, 1, 4, 3, 4, 2, 4, 3, 4,
19020b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov       0, 4, 3, 4, 2, 4, 3, 4, 1, 4, 3, 4, 2, 4, 3, 4,
19021b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov       0, 4, 3, 4, 2, 4, 3, 4, 1, 4, 3, 4, 2, 4, 3, 4,
19022b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov       0, 4, 3, 4, 2, 4, 3, 4, 1, 4, 3, 4, 2, 4, 3, 4,
19023b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov       0, 4, 3, 4, 2, 4, 3, 4, 1, 4, 3, 4, 2, 4, 3, 4,
19024b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov       0, 4, 3, 4, 2, 4, 3, 4, 1, 4, 3, 4, 2, 4, 3, 4,
19025b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov       0, 4, 3, 4, 2, 4, 3, 4, 1, 4, 3, 4, 2, 4, 3, 4,
19026b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov       0, 4, 3, 4, 2, 4, 4, 4, 1, 4, 4, 4, 4, 4, 4, 4,
19027b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov       0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4
19028b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov     };
19029b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
19030b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
19031ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
19032ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Top-level fn                                         ---*/
19033ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
19034ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
19035ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Disassemble a single instruction into IR.  The instruction
19036ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   is located in host memory at &guest_code[delta]. */
19037ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
19038ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownDisResult disInstr_ARM ( IRSB*        irsb_IN,
19039ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         Bool         (*resteerOkFn) ( void*, Addr64 ),
19040ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         Bool         resteerCisOk,
19041ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         void*        callback_opaque,
19042ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         UChar*       guest_code_IN,
19043ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         Long         delta_ENCODED,
19044ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         Addr64       guest_IP_ENCODED,
19045ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         VexArch      guest_arch,
19046ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         VexArchInfo* archinfo,
19047ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         VexAbiInfo*  abiinfo,
19048ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         Bool         host_bigendian_IN )
19049ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
19050ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   DisResult dres;
19051ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Bool isThumb = (Bool)(guest_IP_ENCODED & 1);
19052ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
19053ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Set globals (see top of this file) */
19054ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(guest_arch == VexArchARM);
19055ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
19056ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   irsb              = irsb_IN;
19057ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   host_is_bigendian = host_bigendian_IN;
19058ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   __curr_is_Thumb   = isThumb;
19059ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
19060ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (isThumb) {
19061ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      guest_R15_curr_instr_notENC = (Addr32)guest_IP_ENCODED - 1;
19062ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
19063ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      guest_R15_curr_instr_notENC = (Addr32)guest_IP_ENCODED;
19064ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
19065ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
19066ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (isThumb) {
19067663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      dres = disInstr_THUMB_WRK ( resteerOkFn,
19068ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                  resteerCisOk, callback_opaque,
19069ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                  &guest_code_IN[delta_ENCODED - 1],
19070ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                  archinfo, abiinfo );
19071ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
19072663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      dres = disInstr_ARM_WRK ( resteerOkFn,
19073ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                resteerCisOk, callback_opaque,
19074ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                &guest_code_IN[delta_ENCODED],
19075ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                archinfo, abiinfo );
19076ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
19077ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
19078ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return dres;
19079ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
19080ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
19081ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Test program for the conversion of IRCmpF64Result values to VFP
19082ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   nzcv values.  See handling of FCMPD et al above. */
19083ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*
19084ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownUInt foo ( UInt x )
19085ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
19086ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt ix    = ((x >> 5) & 3) | (x & 1);
19087ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt termL = (((((ix ^ 1) << 30) - 1) >> 29) + 1);
19088ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt termR = (ix & (ix >> 1) & 1);
19089ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return termL  -  termR;
19090ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
19091ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
19092ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid try ( char* s, UInt ir, UInt req )
19093ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
19094ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt act = foo(ir);
19095ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   printf("%s 0x%02x -> req %d%d%d%d act %d%d%d%d (0x%x)\n",
19096ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          s, ir, (req >> 3) & 1, (req >> 2) & 1,
19097ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 (req >> 1) & 1, (req >> 0) & 1,
19098ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 (act >> 3) & 1, (act >> 2) & 1,
19099ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 (act >> 1) & 1, (act >> 0) & 1, act);
19100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
19101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
19102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
19103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint main ( void )
19104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
19105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   printf("\n");
19106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   try("UN", 0x45, 0b0011);
19107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   try("LT", 0x01, 0b1000);
19108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   try("GT", 0x00, 0b0010);
19109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   try("EQ", 0x40, 0b0110);
19110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   printf("\n");
19111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return 0;
19112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
19113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
19114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
19115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/
19116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- end                                         guest_arm_toIR.c ---*/
19117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/
19118