1
2/*--------------------------------------------------------------------*/
3/*--- begin                                       guest_arm_toIR.c ---*/
4/*--------------------------------------------------------------------*/
5
6/*
7   This file is part of Valgrind, a dynamic binary instrumentation
8   framework.
9
10   Copyright (C) 2004-2012 OpenWorks LLP
11      info@open-works.net
12
13   NEON support is
14   Copyright (C) 2010-2012 Samsung Electronics
15   contributed by Dmitry Zhurikhin <zhur@ispras.ru>
16              and Kirill Batuzov <batuzovk@ispras.ru>
17
18   This program is free software; you can redistribute it and/or
19   modify it under the terms of the GNU General Public License as
20   published by the Free Software Foundation; either version 2 of the
21   License, or (at your option) any later version.
22
23   This program is distributed in the hope that it will be useful, but
24   WITHOUT ANY WARRANTY; without even the implied warranty of
25   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
26   General Public License for more details.
27
28   You should have received a copy of the GNU General Public License
29   along with this program; if not, write to the Free Software
30   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
31   02110-1301, USA.
32
33   The GNU General Public License is contained in the file COPYING.
34*/
35
36/* XXXX thumb to check:
37   that all cases where putIRegT writes r15, we generate a jump.
38
39   All uses of newTemp assign to an IRTemp and not a UInt
40
41   For all thumb loads and stores, including VFP ones, new-ITSTATE is
42   backed out before the memory op, and restored afterwards.  This
43   needs to happen even after we go uncond.  (and for sure it doesn't
44   happen for VFP loads/stores right now).
45
46   VFP on thumb: check that we exclude all r13/r15 cases that we
47   should.
48
49   XXXX thumb to do: improve the ITSTATE-zeroing optimisation by
50   taking into account the number of insns guarded by an IT.
51
52   remove the nasty hack, in the spechelper, of looking for Or32(...,
53   0xE0) in as the first arg to armg_calculate_condition, and instead
54   use Slice44 as specified in comments in the spechelper.
55
56   add specialisations for armg_calculate_flag_c and _v, as they
57   are moderately often needed in Thumb code.
58
59   Correctness: ITSTATE handling in Thumb SVCs is wrong.
60
61   Correctness (obscure): in m_transtab, when invalidating code
62   address ranges, invalidate up to 18 bytes after the end of the
63   range.  This is because the ITSTATE optimisation at the top of
64   _THUMB_WRK below analyses up to 18 bytes before the start of any
65   given instruction, and so might depend on the invalidated area.
66*/
67
68/* Limitations, etc
69
70   - pretty dodgy exception semantics for {LD,ST}Mxx, no doubt
71
72   - SWP: the restart jump back is Ijk_Boring; it should be
73     Ijk_NoRedir but that's expensive.  See comments on casLE() in
74     guest_x86_toIR.c.
75*/
76
77/* "Special" instructions.
78
79   This instruction decoder can decode four special instructions
80   which mean nothing natively (are no-ops as far as regs/mem are
81   concerned) but have meaning for supporting Valgrind.  A special
82   instruction is flagged by a 16-byte preamble:
83
84      E1A0C1EC E1A0C6EC E1A0CEEC E1A0C9EC
85      (mov r12, r12, ROR #3;   mov r12, r12, ROR #13;
86       mov r12, r12, ROR #29;  mov r12, r12, ROR #19)
87
88   Following that, one of the following 3 are allowed
89   (standard interpretation in parentheses):
90
91      E18AA00A (orr r10,r10,r10)   R3 = client_request ( R4 )
92      E18BB00B (orr r11,r11,r11)   R3 = guest_NRADDR
93      E18CC00C (orr r12,r12,r12)   branch-and-link-to-noredir R4
94
95   Any other bytes following the 16-byte preamble are illegal and
96   constitute a failure in instruction decoding.  This all assumes
97   that the preamble will never occur except in specific code
98   fragments designed for Valgrind to catch.
99*/
100
101/* Translates ARM(v5) code to IR. */
102
103#include "libvex_basictypes.h"
104#include "libvex_ir.h"
105#include "libvex.h"
106#include "libvex_guest_arm.h"
107
108#include "main_util.h"
109#include "main_globals.h"
110#include "guest_generic_bb_to_IR.h"
111#include "guest_arm_defs.h"
112
113
114/*------------------------------------------------------------*/
115/*--- Globals                                              ---*/
116/*------------------------------------------------------------*/
117
118/* These are set at the start of the translation of a instruction, so
119   that we don't have to pass them around endlessly.  CONST means does
120   not change during translation of the instruction.
121*/
122
123/* CONST: is the host bigendian?  This has to do with float vs double
124   register accesses on VFP, but it's complex and not properly thought
125   out. */
126static Bool host_is_bigendian;
127
128/* CONST: The guest address for the instruction currently being
129   translated.  This is the real, "decoded" address (not subject
130   to the CPSR.T kludge). */
131static Addr32 guest_R15_curr_instr_notENC;
132
133/* CONST, FOR ASSERTIONS ONLY.  Indicates whether currently processed
134   insn is Thumb (True) or ARM (False). */
135static Bool __curr_is_Thumb;
136
137/* MOD: The IRSB* into which we're generating code. */
138static IRSB* irsb;
139
140/* These are to do with handling writes to r15.  They are initially
141   set at the start of disInstr_ARM_WRK to indicate no update,
142   possibly updated during the routine, and examined again at the end.
143   If they have been set to indicate a r15 update then a jump is
144   generated.  Note, "explicit" jumps (b, bx, etc) are generated
145   directly, not using this mechanism -- this is intended to handle
146   the implicit-style jumps resulting from (eg) assigning to r15 as
147   the result of insns we wouldn't normally consider branchy. */
148
149/* MOD.  Initially False; set to True iff abovementioned handling is
150   required. */
151static Bool r15written;
152
153/* MOD.  Initially IRTemp_INVALID.  If the r15 branch to be generated
154   is conditional, this holds the gating IRTemp :: Ity_I32.  If the
155   branch to be generated is unconditional, this remains
156   IRTemp_INVALID. */
157static IRTemp r15guard; /* :: Ity_I32, 0 or 1 */
158
159/* MOD.  Initially Ijk_Boring.  If an r15 branch is to be generated,
160   this holds the jump kind. */
161static IRTemp r15kind;
162
163
164/*------------------------------------------------------------*/
165/*--- Debugging output                                     ---*/
166/*------------------------------------------------------------*/
167
168#define DIP(format, args...)           \
169   if (vex_traceflags & VEX_TRACE_FE)  \
170      vex_printf(format, ## args)
171
172#define DIS(buf, format, args...)      \
173   if (vex_traceflags & VEX_TRACE_FE)  \
174      vex_sprintf(buf, format, ## args)
175
176#define ASSERT_IS_THUMB \
177   do { vassert(__curr_is_Thumb); } while (0)
178
179#define ASSERT_IS_ARM \
180   do { vassert(! __curr_is_Thumb); } while (0)
181
182
183/*------------------------------------------------------------*/
184/*--- Helper bits and pieces for deconstructing the        ---*/
185/*--- arm insn stream.                                     ---*/
186/*------------------------------------------------------------*/
187
188/* Do a little-endian load of a 32-bit word, regardless of the
189   endianness of the underlying host. */
190static inline UInt getUIntLittleEndianly ( UChar* p )
191{
192   UInt w = 0;
193   w = (w << 8) | p[3];
194   w = (w << 8) | p[2];
195   w = (w << 8) | p[1];
196   w = (w << 8) | p[0];
197   return w;
198}
199
200/* Do a little-endian load of a 16-bit word, regardless of the
201   endianness of the underlying host. */
202static inline UShort getUShortLittleEndianly ( UChar* p )
203{
204   UShort w = 0;
205   w = (w << 8) | p[1];
206   w = (w << 8) | p[0];
207   return w;
208}
209
210static UInt ROR32 ( UInt x, UInt sh ) {
211   vassert(sh >= 0 && sh < 32);
212   if (sh == 0)
213      return x;
214   else
215      return (x << (32-sh)) | (x >> sh);
216}
217
218static Int popcount32 ( UInt x )
219{
220   Int res = 0, i;
221   for (i = 0; i < 32; i++) {
222      res += (x & 1);
223      x >>= 1;
224   }
225   return res;
226}
227
228static UInt setbit32 ( UInt x, Int ix, UInt b )
229{
230   UInt mask = 1 << ix;
231   x &= ~mask;
232   x |= ((b << ix) & mask);
233   return x;
234}
235
236#define BITS2(_b1,_b0) \
237   (((_b1) << 1) | (_b0))
238
239#define BITS3(_b2,_b1,_b0)                      \
240  (((_b2) << 2) | ((_b1) << 1) | (_b0))
241
242#define BITS4(_b3,_b2,_b1,_b0) \
243   (((_b3) << 3) | ((_b2) << 2) | ((_b1) << 1) | (_b0))
244
245#define BITS8(_b7,_b6,_b5,_b4,_b3,_b2,_b1,_b0)  \
246   ((BITS4((_b7),(_b6),(_b5),(_b4)) << 4) \
247    | BITS4((_b3),(_b2),(_b1),(_b0)))
248
249#define BITS5(_b4,_b3,_b2,_b1,_b0)  \
250   (BITS8(0,0,0,(_b4),(_b3),(_b2),(_b1),(_b0)))
251#define BITS6(_b5,_b4,_b3,_b2,_b1,_b0)  \
252   (BITS8(0,0,(_b5),(_b4),(_b3),(_b2),(_b1),(_b0)))
253#define BITS7(_b6,_b5,_b4,_b3,_b2,_b1,_b0)  \
254   (BITS8(0,(_b6),(_b5),(_b4),(_b3),(_b2),(_b1),(_b0)))
255
256#define BITS9(_b8,_b7,_b6,_b5,_b4,_b3,_b2,_b1,_b0)      \
257   (((_b8) << 8) \
258    | BITS8((_b7),(_b6),(_b5),(_b4),(_b3),(_b2),(_b1),(_b0)))
259
260#define BITS10(_b9,_b8,_b7,_b6,_b5,_b4,_b3,_b2,_b1,_b0)  \
261   (((_b9) << 9) | ((_b8) << 8)                                \
262    | BITS8((_b7),(_b6),(_b5),(_b4),(_b3),(_b2),(_b1),(_b0)))
263
264/* produces _uint[_bMax:_bMin] */
265#define SLICE_UInt(_uint,_bMax,_bMin) \
266   (( ((UInt)(_uint)) >> (_bMin)) \
267    & (UInt)((1ULL << ((_bMax) - (_bMin) + 1)) - 1ULL))
268
269
270/*------------------------------------------------------------*/
271/*--- Helper bits and pieces for creating IR fragments.    ---*/
272/*------------------------------------------------------------*/
273
274static IRExpr* mkU64 ( ULong i )
275{
276   return IRExpr_Const(IRConst_U64(i));
277}
278
279static IRExpr* mkU32 ( UInt i )
280{
281   return IRExpr_Const(IRConst_U32(i));
282}
283
284static IRExpr* mkU8 ( UInt i )
285{
286   vassert(i < 256);
287   return IRExpr_Const(IRConst_U8( (UChar)i ));
288}
289
290static IRExpr* mkexpr ( IRTemp tmp )
291{
292   return IRExpr_RdTmp(tmp);
293}
294
295static IRExpr* unop ( IROp op, IRExpr* a )
296{
297   return IRExpr_Unop(op, a);
298}
299
300static IRExpr* binop ( IROp op, IRExpr* a1, IRExpr* a2 )
301{
302   return IRExpr_Binop(op, a1, a2);
303}
304
305static IRExpr* triop ( IROp op, IRExpr* a1, IRExpr* a2, IRExpr* a3 )
306{
307   return IRExpr_Triop(op, a1, a2, a3);
308}
309
310static IRExpr* loadLE ( IRType ty, IRExpr* addr )
311{
312   return IRExpr_Load(Iend_LE, ty, addr);
313}
314
315/* Add a statement to the list held by "irbb". */
316static void stmt ( IRStmt* st )
317{
318   addStmtToIRSB( irsb, st );
319}
320
321static void assign ( IRTemp dst, IRExpr* e )
322{
323   stmt( IRStmt_WrTmp(dst, e) );
324}
325
326static void storeLE ( IRExpr* addr, IRExpr* data )
327{
328   stmt( IRStmt_Store(Iend_LE, addr, data) );
329}
330
331/* Generate a new temporary of the given type. */
332static IRTemp newTemp ( IRType ty )
333{
334   vassert(isPlausibleIRType(ty));
335   return newIRTemp( irsb->tyenv, ty );
336}
337
338/* Produces a value in 0 .. 3, which is encoded as per the type
339   IRRoundingMode. */
340static IRExpr* /* :: Ity_I32 */ get_FAKE_roundingmode ( void )
341{
342   return mkU32(Irrm_NEAREST);
343}
344
345/* Generate an expression for SRC rotated right by ROT. */
346static IRExpr* genROR32( IRTemp src, Int rot )
347{
348   vassert(rot >= 0 && rot < 32);
349   if (rot == 0)
350      return mkexpr(src);
351   return
352      binop(Iop_Or32,
353            binop(Iop_Shl32, mkexpr(src), mkU8(32 - rot)),
354            binop(Iop_Shr32, mkexpr(src), mkU8(rot)));
355}
356
357static IRExpr* mkU128 ( ULong i )
358{
359   return binop(Iop_64HLtoV128, mkU64(i), mkU64(i));
360}
361
362/* Generate a 4-aligned version of the given expression if
363   the given condition is true.  Else return it unchanged. */
364static IRExpr* align4if ( IRExpr* e, Bool b )
365{
366   if (b)
367      return binop(Iop_And32, e, mkU32(~3));
368   else
369      return e;
370}
371
372
373/*------------------------------------------------------------*/
374/*--- Helpers for accessing guest registers.               ---*/
375/*------------------------------------------------------------*/
376
377#define OFFB_R0       offsetof(VexGuestARMState,guest_R0)
378#define OFFB_R1       offsetof(VexGuestARMState,guest_R1)
379#define OFFB_R2       offsetof(VexGuestARMState,guest_R2)
380#define OFFB_R3       offsetof(VexGuestARMState,guest_R3)
381#define OFFB_R4       offsetof(VexGuestARMState,guest_R4)
382#define OFFB_R5       offsetof(VexGuestARMState,guest_R5)
383#define OFFB_R6       offsetof(VexGuestARMState,guest_R6)
384#define OFFB_R7       offsetof(VexGuestARMState,guest_R7)
385#define OFFB_R8       offsetof(VexGuestARMState,guest_R8)
386#define OFFB_R9       offsetof(VexGuestARMState,guest_R9)
387#define OFFB_R10      offsetof(VexGuestARMState,guest_R10)
388#define OFFB_R11      offsetof(VexGuestARMState,guest_R11)
389#define OFFB_R12      offsetof(VexGuestARMState,guest_R12)
390#define OFFB_R13      offsetof(VexGuestARMState,guest_R13)
391#define OFFB_R14      offsetof(VexGuestARMState,guest_R14)
392#define OFFB_R15T     offsetof(VexGuestARMState,guest_R15T)
393
394#define OFFB_CC_OP    offsetof(VexGuestARMState,guest_CC_OP)
395#define OFFB_CC_DEP1  offsetof(VexGuestARMState,guest_CC_DEP1)
396#define OFFB_CC_DEP2  offsetof(VexGuestARMState,guest_CC_DEP2)
397#define OFFB_CC_NDEP  offsetof(VexGuestARMState,guest_CC_NDEP)
398#define OFFB_NRADDR   offsetof(VexGuestARMState,guest_NRADDR)
399
400#define OFFB_D0       offsetof(VexGuestARMState,guest_D0)
401#define OFFB_D1       offsetof(VexGuestARMState,guest_D1)
402#define OFFB_D2       offsetof(VexGuestARMState,guest_D2)
403#define OFFB_D3       offsetof(VexGuestARMState,guest_D3)
404#define OFFB_D4       offsetof(VexGuestARMState,guest_D4)
405#define OFFB_D5       offsetof(VexGuestARMState,guest_D5)
406#define OFFB_D6       offsetof(VexGuestARMState,guest_D6)
407#define OFFB_D7       offsetof(VexGuestARMState,guest_D7)
408#define OFFB_D8       offsetof(VexGuestARMState,guest_D8)
409#define OFFB_D9       offsetof(VexGuestARMState,guest_D9)
410#define OFFB_D10      offsetof(VexGuestARMState,guest_D10)
411#define OFFB_D11      offsetof(VexGuestARMState,guest_D11)
412#define OFFB_D12      offsetof(VexGuestARMState,guest_D12)
413#define OFFB_D13      offsetof(VexGuestARMState,guest_D13)
414#define OFFB_D14      offsetof(VexGuestARMState,guest_D14)
415#define OFFB_D15      offsetof(VexGuestARMState,guest_D15)
416#define OFFB_D16      offsetof(VexGuestARMState,guest_D16)
417#define OFFB_D17      offsetof(VexGuestARMState,guest_D17)
418#define OFFB_D18      offsetof(VexGuestARMState,guest_D18)
419#define OFFB_D19      offsetof(VexGuestARMState,guest_D19)
420#define OFFB_D20      offsetof(VexGuestARMState,guest_D20)
421#define OFFB_D21      offsetof(VexGuestARMState,guest_D21)
422#define OFFB_D22      offsetof(VexGuestARMState,guest_D22)
423#define OFFB_D23      offsetof(VexGuestARMState,guest_D23)
424#define OFFB_D24      offsetof(VexGuestARMState,guest_D24)
425#define OFFB_D25      offsetof(VexGuestARMState,guest_D25)
426#define OFFB_D26      offsetof(VexGuestARMState,guest_D26)
427#define OFFB_D27      offsetof(VexGuestARMState,guest_D27)
428#define OFFB_D28      offsetof(VexGuestARMState,guest_D28)
429#define OFFB_D29      offsetof(VexGuestARMState,guest_D29)
430#define OFFB_D30      offsetof(VexGuestARMState,guest_D30)
431#define OFFB_D31      offsetof(VexGuestARMState,guest_D31)
432
433#define OFFB_FPSCR    offsetof(VexGuestARMState,guest_FPSCR)
434#define OFFB_TPIDRURO offsetof(VexGuestARMState,guest_TPIDRURO)
435#define OFFB_ITSTATE  offsetof(VexGuestARMState,guest_ITSTATE)
436#define OFFB_QFLAG32  offsetof(VexGuestARMState,guest_QFLAG32)
437#define OFFB_GEFLAG0  offsetof(VexGuestARMState,guest_GEFLAG0)
438#define OFFB_GEFLAG1  offsetof(VexGuestARMState,guest_GEFLAG1)
439#define OFFB_GEFLAG2  offsetof(VexGuestARMState,guest_GEFLAG2)
440#define OFFB_GEFLAG3  offsetof(VexGuestARMState,guest_GEFLAG3)
441
442
443/* ---------------- Integer registers ---------------- */
444
445static Int integerGuestRegOffset ( UInt iregNo )
446{
447   /* Do we care about endianness here?  We do if sub-parts of integer
448      registers are accessed, but I don't think that ever happens on
449      ARM. */
450   switch (iregNo) {
451      case 0:  return OFFB_R0;
452      case 1:  return OFFB_R1;
453      case 2:  return OFFB_R2;
454      case 3:  return OFFB_R3;
455      case 4:  return OFFB_R4;
456      case 5:  return OFFB_R5;
457      case 6:  return OFFB_R6;
458      case 7:  return OFFB_R7;
459      case 8:  return OFFB_R8;
460      case 9:  return OFFB_R9;
461      case 10: return OFFB_R10;
462      case 11: return OFFB_R11;
463      case 12: return OFFB_R12;
464      case 13: return OFFB_R13;
465      case 14: return OFFB_R14;
466      case 15: return OFFB_R15T;
467      default: vassert(0);
468   }
469}
470
471/* Plain ("low level") read from a reg; no +8 offset magic for r15. */
472static IRExpr* llGetIReg ( UInt iregNo )
473{
474   vassert(iregNo < 16);
475   return IRExpr_Get( integerGuestRegOffset(iregNo), Ity_I32 );
476}
477
478/* Architected read from a reg in ARM mode.  This automagically adds 8
479   to all reads of r15. */
480static IRExpr* getIRegA ( UInt iregNo )
481{
482   IRExpr* e;
483   ASSERT_IS_ARM;
484   vassert(iregNo < 16);
485   if (iregNo == 15) {
486      /* If asked for r15, don't read the guest state value, as that
487         may not be up to date in the case where loop unrolling has
488         happened, because the first insn's write to the block is
489         omitted; hence in the 2nd and subsequent unrollings we don't
490         have a correct value in guest r15.  Instead produce the
491         constant that we know would be produced at this point. */
492      vassert(0 == (guest_R15_curr_instr_notENC & 3));
493      e = mkU32(guest_R15_curr_instr_notENC + 8);
494   } else {
495      e = IRExpr_Get( integerGuestRegOffset(iregNo), Ity_I32 );
496   }
497   return e;
498}
499
500/* Architected read from a reg in Thumb mode.  This automagically adds
501   4 to all reads of r15. */
502static IRExpr* getIRegT ( UInt iregNo )
503{
504   IRExpr* e;
505   ASSERT_IS_THUMB;
506   vassert(iregNo < 16);
507   if (iregNo == 15) {
508      /* Ditto comment in getIReg. */
509      vassert(0 == (guest_R15_curr_instr_notENC & 1));
510      e = mkU32(guest_R15_curr_instr_notENC + 4);
511   } else {
512      e = IRExpr_Get( integerGuestRegOffset(iregNo), Ity_I32 );
513   }
514   return e;
515}
516
517/* Plain ("low level") write to a reg; no jump or alignment magic for
518   r15. */
519static void llPutIReg ( UInt iregNo, IRExpr* e )
520{
521   vassert(iregNo < 16);
522   vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I32);
523   stmt( IRStmt_Put(integerGuestRegOffset(iregNo), e) );
524}
525
526/* Architected write to an integer register in ARM mode.  If it is to
527   r15, record info so at the end of this insn's translation, a branch
528   to it can be made.  Also handles conditional writes to the
529   register: if guardT == IRTemp_INVALID then the write is
530   unconditional.  If writing r15, also 4-align it. */
531static void putIRegA ( UInt       iregNo,
532                       IRExpr*    e,
533                       IRTemp     guardT /* :: Ity_I32, 0 or 1 */,
534                       IRJumpKind jk /* if a jump is generated */ )
535{
536   /* if writing r15, force e to be 4-aligned. */
537   // INTERWORKING FIXME.  this needs to be relaxed so that
538   // puts caused by LDMxx which load r15 interwork right.
539   // but is no aligned too relaxed?
540   //if (iregNo == 15)
541   //   e = binop(Iop_And32, e, mkU32(~3));
542   ASSERT_IS_ARM;
543   /* So, generate either an unconditional or a conditional write to
544      the reg. */
545   if (guardT == IRTemp_INVALID) {
546      /* unconditional write */
547      llPutIReg( iregNo, e );
548   } else {
549      llPutIReg( iregNo,
550                 IRExpr_Mux0X( unop(Iop_32to8, mkexpr(guardT)),
551                               llGetIReg(iregNo),
552                               e ));
553   }
554   if (iregNo == 15) {
555      // assert against competing r15 updates.  Shouldn't
556      // happen; should be ruled out by the instr matching
557      // logic.
558      vassert(r15written == False);
559      vassert(r15guard   == IRTemp_INVALID);
560      vassert(r15kind    == Ijk_Boring);
561      r15written = True;
562      r15guard   = guardT;
563      r15kind    = jk;
564   }
565}
566
567
568/* Architected write to an integer register in Thumb mode.  Writes to
569   r15 are not allowed.  Handles conditional writes to the register:
570   if guardT == IRTemp_INVALID then the write is unconditional. */
571static void putIRegT ( UInt       iregNo,
572                       IRExpr*    e,
573                       IRTemp     guardT /* :: Ity_I32, 0 or 1 */ )
574{
575   /* So, generate either an unconditional or a conditional write to
576      the reg. */
577   ASSERT_IS_THUMB;
578   vassert(iregNo >= 0 && iregNo <= 14);
579   if (guardT == IRTemp_INVALID) {
580      /* unconditional write */
581      llPutIReg( iregNo, e );
582   } else {
583      llPutIReg( iregNo,
584                 IRExpr_Mux0X( unop(Iop_32to8, mkexpr(guardT)),
585                               llGetIReg(iregNo),
586                               e ));
587   }
588}
589
590
591/* Thumb16 and Thumb32 only.
592   Returns true if reg is 13 or 15.  Implements the BadReg
593   predicate in the ARM ARM. */
594static Bool isBadRegT ( UInt r )
595{
596   vassert(r <= 15);
597   ASSERT_IS_THUMB;
598   return r == 13 || r == 15;
599}
600
601
602/* ---------------- Double registers ---------------- */
603
604static Int doubleGuestRegOffset ( UInt dregNo )
605{
606   /* Do we care about endianness here?  Probably do if we ever get
607      into the situation of dealing with the single-precision VFP
608      registers. */
609   switch (dregNo) {
610      case 0:  return OFFB_D0;
611      case 1:  return OFFB_D1;
612      case 2:  return OFFB_D2;
613      case 3:  return OFFB_D3;
614      case 4:  return OFFB_D4;
615      case 5:  return OFFB_D5;
616      case 6:  return OFFB_D6;
617      case 7:  return OFFB_D7;
618      case 8:  return OFFB_D8;
619      case 9:  return OFFB_D9;
620      case 10: return OFFB_D10;
621      case 11: return OFFB_D11;
622      case 12: return OFFB_D12;
623      case 13: return OFFB_D13;
624      case 14: return OFFB_D14;
625      case 15: return OFFB_D15;
626      case 16: return OFFB_D16;
627      case 17: return OFFB_D17;
628      case 18: return OFFB_D18;
629      case 19: return OFFB_D19;
630      case 20: return OFFB_D20;
631      case 21: return OFFB_D21;
632      case 22: return OFFB_D22;
633      case 23: return OFFB_D23;
634      case 24: return OFFB_D24;
635      case 25: return OFFB_D25;
636      case 26: return OFFB_D26;
637      case 27: return OFFB_D27;
638      case 28: return OFFB_D28;
639      case 29: return OFFB_D29;
640      case 30: return OFFB_D30;
641      case 31: return OFFB_D31;
642      default: vassert(0);
643   }
644}
645
646/* Plain ("low level") read from a VFP Dreg. */
647static IRExpr* llGetDReg ( UInt dregNo )
648{
649   vassert(dregNo < 32);
650   return IRExpr_Get( doubleGuestRegOffset(dregNo), Ity_F64 );
651}
652
653/* Architected read from a VFP Dreg. */
654static IRExpr* getDReg ( UInt dregNo ) {
655   return llGetDReg( dregNo );
656}
657
658/* Plain ("low level") write to a VFP Dreg. */
659static void llPutDReg ( UInt dregNo, IRExpr* e )
660{
661   vassert(dregNo < 32);
662   vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_F64);
663   stmt( IRStmt_Put(doubleGuestRegOffset(dregNo), e) );
664}
665
666/* Architected write to a VFP Dreg.  Handles conditional writes to the
667   register: if guardT == IRTemp_INVALID then the write is
668   unconditional. */
669static void putDReg ( UInt    dregNo,
670                      IRExpr* e,
671                      IRTemp  guardT /* :: Ity_I32, 0 or 1 */)
672{
673   /* So, generate either an unconditional or a conditional write to
674      the reg. */
675   if (guardT == IRTemp_INVALID) {
676      /* unconditional write */
677      llPutDReg( dregNo, e );
678   } else {
679      llPutDReg( dregNo,
680                 IRExpr_Mux0X( unop(Iop_32to8, mkexpr(guardT)),
681                               llGetDReg(dregNo),
682                               e ));
683   }
684}
685
686/* And now exactly the same stuff all over again, but this time
687   taking/returning I64 rather than F64, to support 64-bit Neon
688   ops. */
689
690/* Plain ("low level") read from a Neon Integer Dreg. */
691static IRExpr* llGetDRegI64 ( UInt dregNo )
692{
693   vassert(dregNo < 32);
694   return IRExpr_Get( doubleGuestRegOffset(dregNo), Ity_I64 );
695}
696
697/* Architected read from a Neon Integer Dreg. */
698static IRExpr* getDRegI64 ( UInt dregNo ) {
699   return llGetDRegI64( dregNo );
700}
701
702/* Plain ("low level") write to a Neon Integer Dreg. */
703static void llPutDRegI64 ( UInt dregNo, IRExpr* e )
704{
705   vassert(dregNo < 32);
706   vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I64);
707   stmt( IRStmt_Put(doubleGuestRegOffset(dregNo), e) );
708}
709
710/* Architected write to a Neon Integer Dreg.  Handles conditional
711   writes to the register: if guardT == IRTemp_INVALID then the write
712   is unconditional. */
713static void putDRegI64 ( UInt    dregNo,
714                         IRExpr* e,
715                         IRTemp  guardT /* :: Ity_I32, 0 or 1 */)
716{
717   /* So, generate either an unconditional or a conditional write to
718      the reg. */
719   if (guardT == IRTemp_INVALID) {
720      /* unconditional write */
721      llPutDRegI64( dregNo, e );
722   } else {
723      llPutDRegI64( dregNo,
724                    IRExpr_Mux0X( unop(Iop_32to8, mkexpr(guardT)),
725                                  llGetDRegI64(dregNo),
726                                  e ));
727   }
728}
729
730/* ---------------- Quad registers ---------------- */
731
732static Int quadGuestRegOffset ( UInt qregNo )
733{
734   /* Do we care about endianness here?  Probably do if we ever get
735      into the situation of dealing with the 64 bit Neon registers. */
736   switch (qregNo) {
737      case 0:  return OFFB_D0;
738      case 1:  return OFFB_D2;
739      case 2:  return OFFB_D4;
740      case 3:  return OFFB_D6;
741      case 4:  return OFFB_D8;
742      case 5:  return OFFB_D10;
743      case 6:  return OFFB_D12;
744      case 7:  return OFFB_D14;
745      case 8:  return OFFB_D16;
746      case 9:  return OFFB_D18;
747      case 10: return OFFB_D20;
748      case 11: return OFFB_D22;
749      case 12: return OFFB_D24;
750      case 13: return OFFB_D26;
751      case 14: return OFFB_D28;
752      case 15: return OFFB_D30;
753      default: vassert(0);
754   }
755}
756
757/* Plain ("low level") read from a Neon Qreg. */
758static IRExpr* llGetQReg ( UInt qregNo )
759{
760   vassert(qregNo < 16);
761   return IRExpr_Get( quadGuestRegOffset(qregNo), Ity_V128 );
762}
763
764/* Architected read from a Neon Qreg. */
765static IRExpr* getQReg ( UInt qregNo ) {
766   return llGetQReg( qregNo );
767}
768
769/* Plain ("low level") write to a Neon Qreg. */
770static void llPutQReg ( UInt qregNo, IRExpr* e )
771{
772   vassert(qregNo < 16);
773   vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_V128);
774   stmt( IRStmt_Put(quadGuestRegOffset(qregNo), e) );
775}
776
777/* Architected write to a Neon Qreg.  Handles conditional writes to the
778   register: if guardT == IRTemp_INVALID then the write is
779   unconditional. */
780static void putQReg ( UInt    qregNo,
781                      IRExpr* e,
782                      IRTemp  guardT /* :: Ity_I32, 0 or 1 */)
783{
784   /* So, generate either an unconditional or a conditional write to
785      the reg. */
786   if (guardT == IRTemp_INVALID) {
787      /* unconditional write */
788      llPutQReg( qregNo, e );
789   } else {
790      llPutQReg( qregNo,
791                 IRExpr_Mux0X( unop(Iop_32to8, mkexpr(guardT)),
792                               llGetQReg(qregNo),
793                               e ));
794   }
795}
796
797
798/* ---------------- Float registers ---------------- */
799
800static Int floatGuestRegOffset ( UInt fregNo )
801{
802   /* Start with the offset of the containing double, and then correct
803      for endianness.  Actually this is completely bogus and needs
804      careful thought. */
805   Int off;
806   vassert(fregNo < 32);
807   off = doubleGuestRegOffset(fregNo >> 1);
808   if (host_is_bigendian) {
809      vassert(0);
810   } else {
811      if (fregNo & 1)
812         off += 4;
813   }
814   return off;
815}
816
817/* Plain ("low level") read from a VFP Freg. */
818static IRExpr* llGetFReg ( UInt fregNo )
819{
820   vassert(fregNo < 32);
821   return IRExpr_Get( floatGuestRegOffset(fregNo), Ity_F32 );
822}
823
824/* Architected read from a VFP Freg. */
825static IRExpr* getFReg ( UInt fregNo ) {
826   return llGetFReg( fregNo );
827}
828
829/* Plain ("low level") write to a VFP Freg. */
830static void llPutFReg ( UInt fregNo, IRExpr* e )
831{
832   vassert(fregNo < 32);
833   vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_F32);
834   stmt( IRStmt_Put(floatGuestRegOffset(fregNo), e) );
835}
836
837/* Architected write to a VFP Freg.  Handles conditional writes to the
838   register: if guardT == IRTemp_INVALID then the write is
839   unconditional. */
840static void putFReg ( UInt    fregNo,
841                      IRExpr* e,
842                      IRTemp  guardT /* :: Ity_I32, 0 or 1 */)
843{
844   /* So, generate either an unconditional or a conditional write to
845      the reg. */
846   if (guardT == IRTemp_INVALID) {
847      /* unconditional write */
848      llPutFReg( fregNo, e );
849   } else {
850      llPutFReg( fregNo,
851                 IRExpr_Mux0X( unop(Iop_32to8, mkexpr(guardT)),
852                               llGetFReg(fregNo),
853                               e ));
854   }
855}
856
857
858/* ---------------- Misc registers ---------------- */
859
860static void putMiscReg32 ( UInt    gsoffset,
861                           IRExpr* e, /* :: Ity_I32 */
862                           IRTemp  guardT /* :: Ity_I32, 0 or 1 */)
863{
864   switch (gsoffset) {
865      case OFFB_FPSCR:   break;
866      case OFFB_QFLAG32: break;
867      case OFFB_GEFLAG0: break;
868      case OFFB_GEFLAG1: break;
869      case OFFB_GEFLAG2: break;
870      case OFFB_GEFLAG3: break;
871      default: vassert(0); /* awaiting more cases */
872   }
873   vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I32);
874
875   if (guardT == IRTemp_INVALID) {
876      /* unconditional write */
877      stmt(IRStmt_Put(gsoffset, e));
878   } else {
879      stmt(IRStmt_Put(
880         gsoffset,
881         IRExpr_Mux0X( unop(Iop_32to8, mkexpr(guardT)),
882                       IRExpr_Get(gsoffset, Ity_I32),
883                       e
884         )
885      ));
886   }
887}
888
889static IRTemp get_ITSTATE ( void )
890{
891   ASSERT_IS_THUMB;
892   IRTemp t = newTemp(Ity_I32);
893   assign(t, IRExpr_Get( OFFB_ITSTATE, Ity_I32));
894   return t;
895}
896
897static void put_ITSTATE ( IRTemp t )
898{
899   ASSERT_IS_THUMB;
900   stmt( IRStmt_Put( OFFB_ITSTATE, mkexpr(t)) );
901}
902
903static IRTemp get_QFLAG32 ( void )
904{
905   IRTemp t = newTemp(Ity_I32);
906   assign(t, IRExpr_Get( OFFB_QFLAG32, Ity_I32));
907   return t;
908}
909
910static void put_QFLAG32 ( IRTemp t, IRTemp condT )
911{
912   putMiscReg32( OFFB_QFLAG32, mkexpr(t), condT );
913}
914
915/* Stickily set the 'Q' flag (APSR bit 27) of the APSR (Application Program
916   Status Register) to indicate that overflow or saturation occurred.
917   Nb: t must be zero to denote no saturation, and any nonzero
918   value to indicate saturation. */
919static void or_into_QFLAG32 ( IRExpr* e, IRTemp condT )
920{
921   IRTemp old = get_QFLAG32();
922   IRTemp nyu = newTemp(Ity_I32);
923   assign(nyu, binop(Iop_Or32, mkexpr(old), e) );
924   put_QFLAG32(nyu, condT);
925}
926
927/* Generate code to set APSR.GE[flagNo]. Each fn call sets 1 bit.
928   flagNo: which flag bit to set [3...0]
929   lowbits_to_ignore:  0 = look at all 32 bits
930                       8 = look at top 24 bits only
931                      16 = look at top 16 bits only
932                      31 = look at the top bit only
933   e: input value to be evaluated.
934   The new value is taken from 'e' with the lowest 'lowbits_to_ignore'
935   masked out.  If the resulting value is zero then the GE flag is
936   set to 0; any other value sets the flag to 1. */
937static void put_GEFLAG32 ( Int flagNo,            /* 0, 1, 2 or 3 */
938                           Int lowbits_to_ignore, /* 0, 8, 16 or 31   */
939                           IRExpr* e,             /* Ity_I32 */
940                           IRTemp condT )
941{
942   vassert( flagNo >= 0 && flagNo <= 3 );
943   vassert( lowbits_to_ignore == 0  ||
944            lowbits_to_ignore == 8  ||
945            lowbits_to_ignore == 16 ||
946            lowbits_to_ignore == 31 );
947   IRTemp masked = newTemp(Ity_I32);
948   assign(masked, binop(Iop_Shr32, e, mkU8(lowbits_to_ignore)));
949
950   switch (flagNo) {
951      case 0: putMiscReg32(OFFB_GEFLAG0, mkexpr(masked), condT); break;
952      case 1: putMiscReg32(OFFB_GEFLAG1, mkexpr(masked), condT); break;
953      case 2: putMiscReg32(OFFB_GEFLAG2, mkexpr(masked), condT); break;
954      case 3: putMiscReg32(OFFB_GEFLAG3, mkexpr(masked), condT); break;
955      default: vassert(0);
956   }
957}
958
959/* Return the (32-bit, zero-or-nonzero representation scheme) of
960   the specified GE flag. */
961static IRExpr* get_GEFLAG32( Int flagNo /* 0, 1, 2, 3 */ )
962{
963   switch (flagNo) {
964      case 0: return IRExpr_Get( OFFB_GEFLAG0, Ity_I32 );
965      case 1: return IRExpr_Get( OFFB_GEFLAG1, Ity_I32 );
966      case 2: return IRExpr_Get( OFFB_GEFLAG2, Ity_I32 );
967      case 3: return IRExpr_Get( OFFB_GEFLAG3, Ity_I32 );
968      default: vassert(0);
969   }
970}
971
972/* Set all 4 GE flags from the given 32-bit value as follows: GE 3 and
973   2 are set from bit 31 of the value, and GE 1 and 0 are set from bit
974   15 of the value.  All other bits are ignored. */
975static void set_GE_32_10_from_bits_31_15 ( IRTemp t32, IRTemp condT )
976{
977   IRTemp ge10 = newTemp(Ity_I32);
978   IRTemp ge32 = newTemp(Ity_I32);
979   assign(ge10, binop(Iop_And32, mkexpr(t32), mkU32(0x00008000)));
980   assign(ge32, binop(Iop_And32, mkexpr(t32), mkU32(0x80000000)));
981   put_GEFLAG32( 0, 0, mkexpr(ge10), condT );
982   put_GEFLAG32( 1, 0, mkexpr(ge10), condT );
983   put_GEFLAG32( 2, 0, mkexpr(ge32), condT );
984   put_GEFLAG32( 3, 0, mkexpr(ge32), condT );
985}
986
987
988/* Set all 4 GE flags from the given 32-bit value as follows: GE 3
989   from bit 31, GE 2 from bit 23, GE 1 from bit 15, and GE0 from
990   bit 7.  All other bits are ignored. */
991static void set_GE_3_2_1_0_from_bits_31_23_15_7 ( IRTemp t32, IRTemp condT )
992{
993   IRTemp ge0 = newTemp(Ity_I32);
994   IRTemp ge1 = newTemp(Ity_I32);
995   IRTemp ge2 = newTemp(Ity_I32);
996   IRTemp ge3 = newTemp(Ity_I32);
997   assign(ge0, binop(Iop_And32, mkexpr(t32), mkU32(0x00000080)));
998   assign(ge1, binop(Iop_And32, mkexpr(t32), mkU32(0x00008000)));
999   assign(ge2, binop(Iop_And32, mkexpr(t32), mkU32(0x00800000)));
1000   assign(ge3, binop(Iop_And32, mkexpr(t32), mkU32(0x80000000)));
1001   put_GEFLAG32( 0, 0, mkexpr(ge0), condT );
1002   put_GEFLAG32( 1, 0, mkexpr(ge1), condT );
1003   put_GEFLAG32( 2, 0, mkexpr(ge2), condT );
1004   put_GEFLAG32( 3, 0, mkexpr(ge3), condT );
1005}
1006
1007
1008/* ---------------- FPSCR stuff ---------------- */
1009
1010/* Generate IR to get hold of the rounding mode bits in FPSCR, and
1011   convert them to IR format.  Bind the final result to the
1012   returned temp. */
1013static IRTemp /* :: Ity_I32 */ mk_get_IR_rounding_mode ( void )
1014{
1015   /* The ARMvfp encoding for rounding mode bits is:
1016         00  to nearest
1017         01  to +infinity
1018         10  to -infinity
1019         11  to zero
1020      We need to convert that to the IR encoding:
1021         00  to nearest (the default)
1022         10  to +infinity
1023         01  to -infinity
1024         11  to zero
1025      Which can be done by swapping bits 0 and 1.
1026      The rmode bits are at 23:22 in FPSCR.
1027   */
1028   IRTemp armEncd = newTemp(Ity_I32);
1029   IRTemp swapped = newTemp(Ity_I32);
1030   /* Fish FPSCR[23:22] out, and slide to bottom.  Doesn't matter that
1031      we don't zero out bits 24 and above, since the assignment to
1032      'swapped' will mask them out anyway. */
1033   assign(armEncd,
1034          binop(Iop_Shr32, IRExpr_Get(OFFB_FPSCR, Ity_I32), mkU8(22)));
1035   /* Now swap them. */
1036   assign(swapped,
1037          binop(Iop_Or32,
1038                binop(Iop_And32,
1039                      binop(Iop_Shl32, mkexpr(armEncd), mkU8(1)),
1040                      mkU32(2)),
1041                binop(Iop_And32,
1042                      binop(Iop_Shr32, mkexpr(armEncd), mkU8(1)),
1043                      mkU32(1))
1044         ));
1045   return swapped;
1046}
1047
1048
1049/*------------------------------------------------------------*/
1050/*--- Helpers for flag handling and conditional insns      ---*/
1051/*------------------------------------------------------------*/
1052
1053static HChar* name_ARMCondcode ( ARMCondcode cond )
1054{
1055   switch (cond) {
1056      case ARMCondEQ:  return "{eq}";
1057      case ARMCondNE:  return "{ne}";
1058      case ARMCondHS:  return "{hs}";  // or 'cs'
1059      case ARMCondLO:  return "{lo}";  // or 'cc'
1060      case ARMCondMI:  return "{mi}";
1061      case ARMCondPL:  return "{pl}";
1062      case ARMCondVS:  return "{vs}";
1063      case ARMCondVC:  return "{vc}";
1064      case ARMCondHI:  return "{hi}";
1065      case ARMCondLS:  return "{ls}";
1066      case ARMCondGE:  return "{ge}";
1067      case ARMCondLT:  return "{lt}";
1068      case ARMCondGT:  return "{gt}";
1069      case ARMCondLE:  return "{le}";
1070      case ARMCondAL:  return ""; // {al}: is the default
1071      case ARMCondNV:  return "{nv}";
1072      default: vpanic("name_ARMCondcode");
1073   }
1074}
1075/* and a handy shorthand for it */
1076static HChar* nCC ( ARMCondcode cond ) {
1077   return name_ARMCondcode(cond);
1078}
1079
1080
1081/* Build IR to calculate some particular condition from stored
1082   CC_OP/CC_DEP1/CC_DEP2/CC_NDEP.  Returns an expression of type
1083   Ity_I32, suitable for narrowing.  Although the return type is
1084   Ity_I32, the returned value is either 0 or 1.  'cond' must be
1085   :: Ity_I32 and must denote the condition to compute in
1086   bits 7:4, and be zero everywhere else.
1087*/
1088static IRExpr* mk_armg_calculate_condition_dyn ( IRExpr* cond )
1089{
1090   vassert(typeOfIRExpr(irsb->tyenv, cond) == Ity_I32);
1091   /* And 'cond' had better produce a value in which only bits 7:4 are
1092      nonzero.  However, obviously we can't assert for that. */
1093
1094   /* So what we're constructing for the first argument is
1095      "(cond << 4) | stored-operation".
1096      However, as per comments above, 'cond' must be supplied
1097      pre-shifted to this function.
1098
1099      This pairing scheme requires that the ARM_CC_OP_ values all fit
1100      in 4 bits.  Hence we are passing a (COND, OP) pair in the lowest
1101      8 bits of the first argument. */
1102   IRExpr** args
1103      = mkIRExprVec_4(
1104           binop(Iop_Or32, IRExpr_Get(OFFB_CC_OP, Ity_I32), cond),
1105           IRExpr_Get(OFFB_CC_DEP1, Ity_I32),
1106           IRExpr_Get(OFFB_CC_DEP2, Ity_I32),
1107           IRExpr_Get(OFFB_CC_NDEP, Ity_I32)
1108        );
1109   IRExpr* call
1110      = mkIRExprCCall(
1111           Ity_I32,
1112           0/*regparm*/,
1113           "armg_calculate_condition", &armg_calculate_condition,
1114           args
1115        );
1116
1117   /* Exclude the requested condition, OP and NDEP from definedness
1118      checking.  We're only interested in DEP1 and DEP2. */
1119   call->Iex.CCall.cee->mcx_mask = (1<<0) | (1<<3);
1120   return call;
1121}
1122
1123
1124/* Build IR to calculate some particular condition from stored
1125   CC_OP/CC_DEP1/CC_DEP2/CC_NDEP.  Returns an expression of type
1126   Ity_I32, suitable for narrowing.  Although the return type is
1127   Ity_I32, the returned value is either 0 or 1.
1128*/
1129static IRExpr* mk_armg_calculate_condition ( ARMCondcode cond )
1130{
1131  /* First arg is "(cond << 4) | condition".  This requires that the
1132     ARM_CC_OP_ values all fit in 4 bits.  Hence we are passing a
1133     (COND, OP) pair in the lowest 8 bits of the first argument. */
1134   vassert(cond >= 0 && cond <= 15);
1135   return mk_armg_calculate_condition_dyn( mkU32(cond << 4) );
1136}
1137
1138
1139/* Build IR to calculate just the carry flag from stored
1140   CC_OP/CC_DEP1/CC_DEP2/CC_NDEP.  Returns an expression ::
1141   Ity_I32. */
1142static IRExpr* mk_armg_calculate_flag_c ( void )
1143{
1144   IRExpr** args
1145      = mkIRExprVec_4( IRExpr_Get(OFFB_CC_OP,   Ity_I32),
1146                       IRExpr_Get(OFFB_CC_DEP1, Ity_I32),
1147                       IRExpr_Get(OFFB_CC_DEP2, Ity_I32),
1148                       IRExpr_Get(OFFB_CC_NDEP, Ity_I32) );
1149   IRExpr* call
1150      = mkIRExprCCall(
1151           Ity_I32,
1152           0/*regparm*/,
1153           "armg_calculate_flag_c", &armg_calculate_flag_c,
1154           args
1155        );
1156   /* Exclude OP and NDEP from definedness checking.  We're only
1157      interested in DEP1 and DEP2. */
1158   call->Iex.CCall.cee->mcx_mask = (1<<0) | (1<<3);
1159   return call;
1160}
1161
1162
1163/* Build IR to calculate just the overflow flag from stored
1164   CC_OP/CC_DEP1/CC_DEP2/CC_NDEP.  Returns an expression ::
1165   Ity_I32. */
1166static IRExpr* mk_armg_calculate_flag_v ( void )
1167{
1168   IRExpr** args
1169      = mkIRExprVec_4( IRExpr_Get(OFFB_CC_OP,   Ity_I32),
1170                       IRExpr_Get(OFFB_CC_DEP1, Ity_I32),
1171                       IRExpr_Get(OFFB_CC_DEP2, Ity_I32),
1172                       IRExpr_Get(OFFB_CC_NDEP, Ity_I32) );
1173   IRExpr* call
1174      = mkIRExprCCall(
1175           Ity_I32,
1176           0/*regparm*/,
1177           "armg_calculate_flag_v", &armg_calculate_flag_v,
1178           args
1179        );
1180   /* Exclude OP and NDEP from definedness checking.  We're only
1181      interested in DEP1 and DEP2. */
1182   call->Iex.CCall.cee->mcx_mask = (1<<0) | (1<<3);
1183   return call;
1184}
1185
1186
1187/* Build IR to calculate N Z C V in bits 31:28 of the
1188   returned word. */
1189static IRExpr* mk_armg_calculate_flags_nzcv ( void )
1190{
1191   IRExpr** args
1192      = mkIRExprVec_4( IRExpr_Get(OFFB_CC_OP,   Ity_I32),
1193                       IRExpr_Get(OFFB_CC_DEP1, Ity_I32),
1194                       IRExpr_Get(OFFB_CC_DEP2, Ity_I32),
1195                       IRExpr_Get(OFFB_CC_NDEP, Ity_I32) );
1196   IRExpr* call
1197      = mkIRExprCCall(
1198           Ity_I32,
1199           0/*regparm*/,
1200           "armg_calculate_flags_nzcv", &armg_calculate_flags_nzcv,
1201           args
1202        );
1203   /* Exclude OP and NDEP from definedness checking.  We're only
1204      interested in DEP1 and DEP2. */
1205   call->Iex.CCall.cee->mcx_mask = (1<<0) | (1<<3);
1206   return call;
1207}
1208
1209static IRExpr* mk_armg_calculate_flag_qc ( IRExpr* resL, IRExpr* resR, Bool Q )
1210{
1211   IRExpr** args1;
1212   IRExpr** args2;
1213   IRExpr *call1, *call2, *res;
1214
1215   if (Q) {
1216      args1 = mkIRExprVec_4 ( binop(Iop_GetElem32x4, resL, mkU8(0)),
1217                              binop(Iop_GetElem32x4, resL, mkU8(1)),
1218                              binop(Iop_GetElem32x4, resR, mkU8(0)),
1219                              binop(Iop_GetElem32x4, resR, mkU8(1)) );
1220      args2 = mkIRExprVec_4 ( binop(Iop_GetElem32x4, resL, mkU8(2)),
1221                              binop(Iop_GetElem32x4, resL, mkU8(3)),
1222                              binop(Iop_GetElem32x4, resR, mkU8(2)),
1223                              binop(Iop_GetElem32x4, resR, mkU8(3)) );
1224   } else {
1225      args1 = mkIRExprVec_4 ( binop(Iop_GetElem32x2, resL, mkU8(0)),
1226                              binop(Iop_GetElem32x2, resL, mkU8(1)),
1227                              binop(Iop_GetElem32x2, resR, mkU8(0)),
1228                              binop(Iop_GetElem32x2, resR, mkU8(1)) );
1229   }
1230
1231#if 1
1232   call1 = mkIRExprCCall(
1233             Ity_I32,
1234             0/*regparm*/,
1235             "armg_calculate_flag_qc", &armg_calculate_flag_qc,
1236             args1
1237          );
1238   if (Q) {
1239      call2 = mkIRExprCCall(
1240                Ity_I32,
1241                0/*regparm*/,
1242                "armg_calculate_flag_qc", &armg_calculate_flag_qc,
1243                args2
1244             );
1245   }
1246   if (Q) {
1247      res = binop(Iop_Or32, call1, call2);
1248   } else {
1249      res = call1;
1250   }
1251#else
1252   if (Q) {
1253      res = unop(Iop_1Uto32,
1254                 binop(Iop_CmpNE32,
1255                       binop(Iop_Or32,
1256                             binop(Iop_Or32,
1257                                   binop(Iop_Xor32,
1258                                         args1[0],
1259                                         args1[2]),
1260                                   binop(Iop_Xor32,
1261                                         args1[1],
1262                                         args1[3])),
1263                             binop(Iop_Or32,
1264                                   binop(Iop_Xor32,
1265                                         args2[0],
1266                                         args2[2]),
1267                                   binop(Iop_Xor32,
1268                                         args2[1],
1269                                         args2[3]))),
1270                       mkU32(0)));
1271   } else {
1272      res = unop(Iop_1Uto32,
1273                 binop(Iop_CmpNE32,
1274                       binop(Iop_Or32,
1275                             binop(Iop_Xor32,
1276                                   args1[0],
1277                                   args1[2]),
1278                             binop(Iop_Xor32,
1279                                   args1[1],
1280                                   args1[3])),
1281                       mkU32(0)));
1282   }
1283#endif
1284   return res;
1285}
1286
1287// FIXME: this is named wrongly .. looks like a sticky set of
1288// QC, not a write to it.
1289static void setFlag_QC ( IRExpr* resL, IRExpr* resR, Bool Q,
1290                         IRTemp condT )
1291{
1292   putMiscReg32 (OFFB_FPSCR,
1293                 binop(Iop_Or32,
1294                       IRExpr_Get(OFFB_FPSCR, Ity_I32),
1295                       binop(Iop_Shl32,
1296                             mk_armg_calculate_flag_qc(resL, resR, Q),
1297                             mkU8(27))),
1298                 condT);
1299}
1300
1301/* Build IR to conditionally set the flags thunk.  As with putIReg, if
1302   guard is IRTemp_INVALID then it's unconditional, else it holds a
1303   condition :: Ity_I32. */
1304static
1305void setFlags_D1_D2_ND ( UInt cc_op, IRTemp t_dep1,
1306                         IRTemp t_dep2, IRTemp t_ndep,
1307                         IRTemp guardT /* :: Ity_I32, 0 or 1 */ )
1308{
1309   IRTemp c8;
1310   vassert(typeOfIRTemp(irsb->tyenv, t_dep1 == Ity_I32));
1311   vassert(typeOfIRTemp(irsb->tyenv, t_dep2 == Ity_I32));
1312   vassert(typeOfIRTemp(irsb->tyenv, t_ndep == Ity_I32));
1313   vassert(cc_op >= ARMG_CC_OP_COPY && cc_op < ARMG_CC_OP_NUMBER);
1314   if (guardT == IRTemp_INVALID) {
1315      /* unconditional */
1316      stmt( IRStmt_Put( OFFB_CC_OP,   mkU32(cc_op) ));
1317      stmt( IRStmt_Put( OFFB_CC_DEP1, mkexpr(t_dep1) ));
1318      stmt( IRStmt_Put( OFFB_CC_DEP2, mkexpr(t_dep2) ));
1319      stmt( IRStmt_Put( OFFB_CC_NDEP, mkexpr(t_ndep) ));
1320   } else {
1321      /* conditional */
1322      c8 = newTemp(Ity_I8);
1323      assign( c8, unop(Iop_32to8, mkexpr(guardT)) );
1324      stmt( IRStmt_Put(
1325               OFFB_CC_OP,
1326               IRExpr_Mux0X( mkexpr(c8),
1327                             IRExpr_Get(OFFB_CC_OP, Ity_I32),
1328                             mkU32(cc_op) )));
1329      stmt( IRStmt_Put(
1330               OFFB_CC_DEP1,
1331               IRExpr_Mux0X( mkexpr(c8),
1332                             IRExpr_Get(OFFB_CC_DEP1, Ity_I32),
1333                             mkexpr(t_dep1) )));
1334      stmt( IRStmt_Put(
1335               OFFB_CC_DEP2,
1336               IRExpr_Mux0X( mkexpr(c8),
1337                             IRExpr_Get(OFFB_CC_DEP2, Ity_I32),
1338                             mkexpr(t_dep2) )));
1339      stmt( IRStmt_Put(
1340               OFFB_CC_NDEP,
1341               IRExpr_Mux0X( mkexpr(c8),
1342                             IRExpr_Get(OFFB_CC_NDEP, Ity_I32),
1343                             mkexpr(t_ndep) )));
1344   }
1345}
1346
1347
1348/* Minor variant of the above that sets NDEP to zero (if it
1349   sets it at all) */
1350static void setFlags_D1_D2 ( UInt cc_op, IRTemp t_dep1,
1351                             IRTemp t_dep2,
1352                             IRTemp guardT /* :: Ity_I32, 0 or 1 */ )
1353{
1354   IRTemp z32 = newTemp(Ity_I32);
1355   assign( z32, mkU32(0) );
1356   setFlags_D1_D2_ND( cc_op, t_dep1, t_dep2, z32, guardT );
1357}
1358
1359
1360/* Minor variant of the above that sets DEP2 to zero (if it
1361   sets it at all) */
1362static void setFlags_D1_ND ( UInt cc_op, IRTemp t_dep1,
1363                             IRTemp t_ndep,
1364                             IRTemp guardT /* :: Ity_I32, 0 or 1 */ )
1365{
1366   IRTemp z32 = newTemp(Ity_I32);
1367   assign( z32, mkU32(0) );
1368   setFlags_D1_D2_ND( cc_op, t_dep1, z32, t_ndep, guardT );
1369}
1370
1371
1372/* Minor variant of the above that sets DEP2 and NDEP to zero (if it
1373   sets them at all) */
1374static void setFlags_D1 ( UInt cc_op, IRTemp t_dep1,
1375                          IRTemp guardT /* :: Ity_I32, 0 or 1 */ )
1376{
1377   IRTemp z32 = newTemp(Ity_I32);
1378   assign( z32, mkU32(0) );
1379   setFlags_D1_D2_ND( cc_op, t_dep1, z32, z32, guardT );
1380}
1381
1382
1383/* ARM only */
1384/* Generate a side-exit to the next instruction, if the given guard
1385   expression :: Ity_I32 is 0 (note!  the side exit is taken if the
1386   condition is false!)  This is used to skip over conditional
1387   instructions which we can't generate straight-line code for, either
1388   because they are too complex or (more likely) they potentially
1389   generate exceptions.
1390*/
1391static void mk_skip_over_A32_if_cond_is_false (
1392               IRTemp guardT /* :: Ity_I32, 0 or 1 */
1393            )
1394{
1395   ASSERT_IS_ARM;
1396   vassert(guardT != IRTemp_INVALID);
1397   vassert(0 == (guest_R15_curr_instr_notENC & 3));
1398   stmt( IRStmt_Exit(
1399            unop(Iop_Not1, unop(Iop_32to1, mkexpr(guardT))),
1400            Ijk_Boring,
1401            IRConst_U32(toUInt(guest_R15_curr_instr_notENC + 4)),
1402            OFFB_R15T
1403       ));
1404}
1405
1406/* Thumb16 only */
1407/* ditto, but jump over a 16-bit thumb insn */
1408static void mk_skip_over_T16_if_cond_is_false (
1409               IRTemp guardT /* :: Ity_I32, 0 or 1 */
1410            )
1411{
1412   ASSERT_IS_THUMB;
1413   vassert(guardT != IRTemp_INVALID);
1414   vassert(0 == (guest_R15_curr_instr_notENC & 1));
1415   stmt( IRStmt_Exit(
1416            unop(Iop_Not1, unop(Iop_32to1, mkexpr(guardT))),
1417            Ijk_Boring,
1418            IRConst_U32(toUInt((guest_R15_curr_instr_notENC + 2) | 1)),
1419            OFFB_R15T
1420       ));
1421}
1422
1423
1424/* Thumb32 only */
1425/* ditto, but jump over a 32-bit thumb insn */
1426static void mk_skip_over_T32_if_cond_is_false (
1427               IRTemp guardT /* :: Ity_I32, 0 or 1 */
1428            )
1429{
1430   ASSERT_IS_THUMB;
1431   vassert(guardT != IRTemp_INVALID);
1432   vassert(0 == (guest_R15_curr_instr_notENC & 1));
1433   stmt( IRStmt_Exit(
1434            unop(Iop_Not1, unop(Iop_32to1, mkexpr(guardT))),
1435            Ijk_Boring,
1436            IRConst_U32(toUInt((guest_R15_curr_instr_notENC + 4) | 1)),
1437            OFFB_R15T
1438       ));
1439}
1440
1441
1442/* Thumb16 and Thumb32 only
1443   Generate a SIGILL followed by a restart of the current instruction
1444   if the given temp is nonzero. */
1445static void gen_SIGILL_T_if_nonzero ( IRTemp t /* :: Ity_I32 */ )
1446{
1447   ASSERT_IS_THUMB;
1448   vassert(t != IRTemp_INVALID);
1449   vassert(0 == (guest_R15_curr_instr_notENC & 1));
1450   stmt(
1451      IRStmt_Exit(
1452         binop(Iop_CmpNE32, mkexpr(t), mkU32(0)),
1453         Ijk_NoDecode,
1454         IRConst_U32(toUInt(guest_R15_curr_instr_notENC | 1)),
1455         OFFB_R15T
1456      )
1457   );
1458}
1459
1460
1461/* Inspect the old_itstate, and generate a SIGILL if it indicates that
1462   we are currently in an IT block and are not the last in the block.
1463   This also rolls back guest_ITSTATE to its old value before the exit
1464   and restores it to its new value afterwards.  This is so that if
1465   the exit is taken, we have an up to date version of ITSTATE
1466   available.  Without doing that, we have no hope of making precise
1467   exceptions work. */
1468static void gen_SIGILL_T_if_in_but_NLI_ITBlock (
1469               IRTemp old_itstate /* :: Ity_I32 */,
1470               IRTemp new_itstate /* :: Ity_I32 */
1471            )
1472{
1473   ASSERT_IS_THUMB;
1474   put_ITSTATE(old_itstate); // backout
1475   IRTemp guards_for_next3 = newTemp(Ity_I32);
1476   assign(guards_for_next3,
1477          binop(Iop_Shr32, mkexpr(old_itstate), mkU8(8)));
1478   gen_SIGILL_T_if_nonzero(guards_for_next3);
1479   put_ITSTATE(new_itstate); //restore
1480}
1481
1482
1483/* Simpler version of the above, which generates a SIGILL if
1484   we're anywhere within an IT block. */
1485static void gen_SIGILL_T_if_in_ITBlock (
1486               IRTemp old_itstate /* :: Ity_I32 */,
1487               IRTemp new_itstate /* :: Ity_I32 */
1488            )
1489{
1490   put_ITSTATE(old_itstate); // backout
1491   gen_SIGILL_T_if_nonzero(old_itstate);
1492   put_ITSTATE(new_itstate); //restore
1493}
1494
1495
1496/* Generate an APSR value, from the NZCV thunk, and
1497   from QFLAG32 and GEFLAG0 .. GEFLAG3. */
1498static IRTemp synthesise_APSR ( void )
1499{
1500   IRTemp res1 = newTemp(Ity_I32);
1501   // Get NZCV
1502   assign( res1, mk_armg_calculate_flags_nzcv() );
1503   // OR in the Q value
1504   IRTemp res2 = newTemp(Ity_I32);
1505   assign(
1506      res2,
1507      binop(Iop_Or32,
1508            mkexpr(res1),
1509            binop(Iop_Shl32,
1510                  unop(Iop_1Uto32,
1511                       binop(Iop_CmpNE32,
1512                             mkexpr(get_QFLAG32()),
1513                             mkU32(0))),
1514                  mkU8(ARMG_CC_SHIFT_Q)))
1515   );
1516   // OR in GE0 .. GE3
1517   IRExpr* ge0
1518      = unop(Iop_1Uto32, binop(Iop_CmpNE32, get_GEFLAG32(0), mkU32(0)));
1519   IRExpr* ge1
1520      = unop(Iop_1Uto32, binop(Iop_CmpNE32, get_GEFLAG32(1), mkU32(0)));
1521   IRExpr* ge2
1522      = unop(Iop_1Uto32, binop(Iop_CmpNE32, get_GEFLAG32(2), mkU32(0)));
1523   IRExpr* ge3
1524      = unop(Iop_1Uto32, binop(Iop_CmpNE32, get_GEFLAG32(3), mkU32(0)));
1525   IRTemp res3 = newTemp(Ity_I32);
1526   assign(res3,
1527          binop(Iop_Or32,
1528                mkexpr(res2),
1529                binop(Iop_Or32,
1530                      binop(Iop_Or32,
1531                            binop(Iop_Shl32, ge0, mkU8(16)),
1532                            binop(Iop_Shl32, ge1, mkU8(17))),
1533                      binop(Iop_Or32,
1534                            binop(Iop_Shl32, ge2, mkU8(18)),
1535                            binop(Iop_Shl32, ge3, mkU8(19))) )));
1536   return res3;
1537}
1538
1539
1540/* and the inverse transformation: given an APSR value,
1541   set the NZCV thunk, the Q flag, and the GE flags. */
1542static void desynthesise_APSR ( Bool write_nzcvq, Bool write_ge,
1543                                IRTemp apsrT, IRTemp condT )
1544{
1545   vassert(write_nzcvq || write_ge);
1546   if (write_nzcvq) {
1547      // Do NZCV
1548      IRTemp immT = newTemp(Ity_I32);
1549      assign(immT, binop(Iop_And32, mkexpr(apsrT), mkU32(0xF0000000)) );
1550      setFlags_D1(ARMG_CC_OP_COPY, immT, condT);
1551      // Do Q
1552      IRTemp qnewT = newTemp(Ity_I32);
1553      assign(qnewT, binop(Iop_And32, mkexpr(apsrT), mkU32(ARMG_CC_MASK_Q)));
1554      put_QFLAG32(qnewT, condT);
1555   }
1556   if (write_ge) {
1557      // Do GE3..0
1558      put_GEFLAG32(0, 0, binop(Iop_And32, mkexpr(apsrT), mkU32(1<<16)),
1559                   condT);
1560      put_GEFLAG32(1, 0, binop(Iop_And32, mkexpr(apsrT), mkU32(1<<17)),
1561                   condT);
1562      put_GEFLAG32(2, 0, binop(Iop_And32, mkexpr(apsrT), mkU32(1<<18)),
1563                   condT);
1564      put_GEFLAG32(3, 0, binop(Iop_And32, mkexpr(apsrT), mkU32(1<<19)),
1565                   condT);
1566   }
1567}
1568
1569
1570/*------------------------------------------------------------*/
1571/*--- Helpers for saturation                               ---*/
1572/*------------------------------------------------------------*/
1573
1574/* FIXME: absolutely the only diff. between (a) armUnsignedSatQ and
1575   (b) armSignedSatQ is that in (a) the floor is set to 0, whereas in
1576   (b) the floor is computed from the value of imm5.  these two fnsn
1577   should be commoned up. */
1578
1579/* UnsignedSatQ(): 'clamp' each value so it lies between 0 <= x <= (2^N)-1
1580   Optionally return flag resQ saying whether saturation occurred.
1581   See definition in manual, section A2.2.1, page 41
1582   (bits(N), boolean) UnsignedSatQ( integer i, integer N )
1583   {
1584     if ( i > (2^N)-1 ) { result = (2^N)-1; saturated = TRUE; }
1585     elsif ( i < 0 )    { result = 0; saturated = TRUE; }
1586     else               { result = i; saturated = FALSE; }
1587     return ( result<N-1:0>, saturated );
1588   }
1589*/
1590static void armUnsignedSatQ( IRTemp* res,  /* OUT - Ity_I32 */
1591                             IRTemp* resQ, /* OUT - Ity_I32  */
1592                             IRTemp regT,  /* value to clamp - Ity_I32 */
1593                             UInt imm5 )   /* saturation ceiling */
1594{
1595   UInt ceil  = (1 << imm5) - 1;    // (2^imm5)-1
1596   UInt floor = 0;
1597
1598   IRTemp node0 = newTemp(Ity_I32);
1599   IRTemp node1 = newTemp(Ity_I32);
1600   IRTemp node2 = newTemp(Ity_I1);
1601   IRTemp node3 = newTemp(Ity_I32);
1602   IRTemp node4 = newTemp(Ity_I32);
1603   IRTemp node5 = newTemp(Ity_I1);
1604   IRTemp node6 = newTemp(Ity_I32);
1605
1606   assign( node0, mkexpr(regT) );
1607   assign( node1, mkU32(ceil) );
1608   assign( node2, binop( Iop_CmpLT32S, mkexpr(node1), mkexpr(node0) ) );
1609   assign( node3, IRExpr_Mux0X( unop(Iop_1Uto8, mkexpr(node2)),
1610                                mkexpr(node0),
1611                                mkexpr(node1) ) );
1612   assign( node4, mkU32(floor) );
1613   assign( node5, binop( Iop_CmpLT32S, mkexpr(node3), mkexpr(node4) ) );
1614   assign( node6, IRExpr_Mux0X( unop(Iop_1Uto8, mkexpr(node5)),
1615                                mkexpr(node3),
1616                                mkexpr(node4) ) );
1617   assign( *res, mkexpr(node6) );
1618
1619   /* if saturation occurred, then resQ is set to some nonzero value
1620      if sat did not occur, resQ is guaranteed to be zero. */
1621   if (resQ) {
1622      assign( *resQ, binop(Iop_Xor32, mkexpr(*res), mkexpr(regT)) );
1623   }
1624}
1625
1626
1627/* SignedSatQ(): 'clamp' each value so it lies between  -2^N <= x <= (2^N) - 1
1628   Optionally return flag resQ saying whether saturation occurred.
1629   - see definition in manual, section A2.2.1, page 41
1630   (bits(N), boolean ) SignedSatQ( integer i, integer N )
1631   {
1632     if ( i > 2^(N-1) - 1 )    { result = 2^(N-1) - 1; saturated = TRUE; }
1633     elsif ( i < -(2^(N-1)) )  { result = -(2^(N-1));  saturated = FALSE; }
1634     else                      { result = i;           saturated = FALSE; }
1635     return ( result[N-1:0], saturated );
1636   }
1637*/
1638static void armSignedSatQ( IRTemp regT,    /* value to clamp - Ity_I32 */
1639                           UInt imm5,      /* saturation ceiling */
1640                           IRTemp* res,    /* OUT - Ity_I32 */
1641                           IRTemp* resQ )  /* OUT - Ity_I32  */
1642{
1643   Int ceil  =  (1 << (imm5-1)) - 1;  //  (2^(imm5-1))-1
1644   Int floor = -(1 << (imm5-1));      // -(2^(imm5-1))
1645
1646   IRTemp node0 = newTemp(Ity_I32);
1647   IRTemp node1 = newTemp(Ity_I32);
1648   IRTemp node2 = newTemp(Ity_I1);
1649   IRTemp node3 = newTemp(Ity_I32);
1650   IRTemp node4 = newTemp(Ity_I32);
1651   IRTemp node5 = newTemp(Ity_I1);
1652   IRTemp node6 = newTemp(Ity_I32);
1653
1654   assign( node0, mkexpr(regT) );
1655   assign( node1, mkU32(ceil) );
1656   assign( node2, binop( Iop_CmpLT32S, mkexpr(node1), mkexpr(node0) ) );
1657   assign( node3, IRExpr_Mux0X( unop(Iop_1Uto8, mkexpr(node2)),
1658                                mkexpr(node0),  mkexpr(node1) ) );
1659   assign( node4, mkU32(floor) );
1660   assign( node5, binop( Iop_CmpLT32S, mkexpr(node3), mkexpr(node4) ) );
1661   assign( node6, IRExpr_Mux0X( unop(Iop_1Uto8, mkexpr(node5)),
1662                                mkexpr(node3),  mkexpr(node4) ) );
1663   assign( *res, mkexpr(node6) );
1664
1665   /* if saturation occurred, then resQ is set to some nonzero value
1666      if sat did not occur, resQ is guaranteed to be zero. */
1667   if (resQ) {
1668     assign( *resQ, binop(Iop_Xor32, mkexpr(*res), mkexpr(regT)) );
1669   }
1670}
1671
1672
1673/* Compute a value 0 :: I32 or 1 :: I32, indicating whether signed
1674   overflow occurred for 32-bit addition.  Needs both args and the
1675   result.  HD p27. */
1676static
1677IRExpr* signed_overflow_after_Add32 ( IRExpr* resE,
1678                                      IRTemp argL, IRTemp argR )
1679{
1680   IRTemp res = newTemp(Ity_I32);
1681   assign(res, resE);
1682   return
1683      binop( Iop_Shr32,
1684             binop( Iop_And32,
1685                    binop( Iop_Xor32, mkexpr(res), mkexpr(argL) ),
1686                    binop( Iop_Xor32, mkexpr(res), mkexpr(argR) )),
1687             mkU8(31) );
1688}
1689
1690/* Similarly .. also from HD p27 .. */
1691static
1692IRExpr* signed_overflow_after_Sub32 ( IRExpr* resE,
1693                                      IRTemp argL, IRTemp argR )
1694{
1695   IRTemp res = newTemp(Ity_I32);
1696   assign(res, resE);
1697   return
1698      binop( Iop_Shr32,
1699             binop( Iop_And32,
1700                    binop( Iop_Xor32, mkexpr(argL), mkexpr(argR) ),
1701                    binop( Iop_Xor32, mkexpr(res),  mkexpr(argL) )),
1702             mkU8(31) );
1703}
1704
1705
1706/*------------------------------------------------------------*/
1707/*--- Larger helpers                                       ---*/
1708/*------------------------------------------------------------*/
1709
1710/* Compute both the result and new C flag value for a LSL by an imm5
1711   or by a register operand.  May generate reads of the old C value
1712   (hence only safe to use before any writes to guest state happen).
1713   Are factored out so can be used by both ARM and Thumb.
1714
1715   Note that in compute_result_and_C_after_{LSL,LSR,ASR}_by{imm5,reg},
1716   "res" (the result)  is a.k.a. "shop", shifter operand
1717   "newC" (the new C)  is a.k.a. "shco", shifter carry out
1718
1719   The calling convention for res and newC is a bit funny.  They could
1720   be passed by value, but instead are passed by ref.
1721
1722   The C (shco) value computed must be zero in bits 31:1, as the IR
1723   optimisations for flag handling (guest_arm_spechelper) rely on
1724   that, and the slow-path handlers (armg_calculate_flags_nzcv) assert
1725   for it.  Same applies to all these functions that compute shco
1726   after a shift or rotate, not just this one.
1727*/
1728
1729static void compute_result_and_C_after_LSL_by_imm5 (
1730               /*OUT*/HChar* buf,
1731               IRTemp* res,
1732               IRTemp* newC,
1733               IRTemp rMt, UInt shift_amt, /* operands */
1734               UInt rM      /* only for debug printing */
1735            )
1736{
1737   if (shift_amt == 0) {
1738      if (newC) {
1739         assign( *newC, mk_armg_calculate_flag_c() );
1740      }
1741      assign( *res, mkexpr(rMt) );
1742      DIS(buf, "r%u", rM);
1743   } else {
1744      vassert(shift_amt >= 1 && shift_amt <= 31);
1745      if (newC) {
1746         assign( *newC,
1747                 binop(Iop_And32,
1748                       binop(Iop_Shr32, mkexpr(rMt),
1749                                        mkU8(32 - shift_amt)),
1750                       mkU32(1)));
1751      }
1752      assign( *res,
1753              binop(Iop_Shl32, mkexpr(rMt), mkU8(shift_amt)) );
1754      DIS(buf, "r%u, LSL #%u", rM, shift_amt);
1755   }
1756}
1757
1758
1759static void compute_result_and_C_after_LSL_by_reg (
1760               /*OUT*/HChar* buf,
1761               IRTemp* res,
1762               IRTemp* newC,
1763               IRTemp rMt, IRTemp rSt,  /* operands */
1764               UInt rM,    UInt rS      /* only for debug printing */
1765            )
1766{
1767   // shift left in range 0 .. 255
1768   // amt  = rS & 255
1769   // res  = amt < 32 ?  Rm << amt  : 0
1770   // newC = amt == 0     ? oldC  :
1771   //        amt in 1..32 ?  Rm[32-amt]  : 0
1772   IRTemp amtT = newTemp(Ity_I32);
1773   assign( amtT, binop(Iop_And32, mkexpr(rSt), mkU32(255)) );
1774   if (newC) {
1775      /* mux0X(amt == 0,
1776               mux0X(amt < 32,
1777                     0,
1778                     Rm[(32-amt) & 31]),
1779               oldC)
1780      */
1781      /* About the best you can do is pray that iropt is able
1782         to nuke most or all of the following junk. */
1783      IRTemp oldC = newTemp(Ity_I32);
1784      assign(oldC, mk_armg_calculate_flag_c() );
1785      assign(
1786         *newC,
1787         IRExpr_Mux0X(
1788            unop(Iop_1Uto8,
1789                 binop(Iop_CmpEQ32, mkexpr(amtT), mkU32(0))),
1790            IRExpr_Mux0X(
1791               unop(Iop_1Uto8,
1792                    binop(Iop_CmpLE32U, mkexpr(amtT), mkU32(32))),
1793               mkU32(0),
1794               binop(Iop_And32,
1795                     binop(Iop_Shr32,
1796                           mkexpr(rMt),
1797                           unop(Iop_32to8,
1798                                binop(Iop_And32,
1799                                      binop(Iop_Sub32,
1800                                            mkU32(32),
1801                                            mkexpr(amtT)),
1802                                      mkU32(31)
1803                                )
1804                           )
1805                     ),
1806                     mkU32(1)
1807               )
1808            ),
1809            mkexpr(oldC)
1810         )
1811      );
1812   }
1813   // (Rm << (Rs & 31))  &  (((Rs & 255) - 32) >>s 31)
1814   // Lhs of the & limits the shift to 31 bits, so as to
1815   // give known IR semantics.  Rhs of the & is all 1s for
1816   // Rs <= 31 and all 0s for Rs >= 32.
1817   assign(
1818      *res,
1819      binop(
1820         Iop_And32,
1821         binop(Iop_Shl32,
1822               mkexpr(rMt),
1823               unop(Iop_32to8,
1824                    binop(Iop_And32, mkexpr(rSt), mkU32(31)))),
1825         binop(Iop_Sar32,
1826               binop(Iop_Sub32,
1827                     mkexpr(amtT),
1828                     mkU32(32)),
1829               mkU8(31))));
1830    DIS(buf, "r%u, LSL r%u", rM, rS);
1831}
1832
1833
1834static void compute_result_and_C_after_LSR_by_imm5 (
1835               /*OUT*/HChar* buf,
1836               IRTemp* res,
1837               IRTemp* newC,
1838               IRTemp rMt, UInt shift_amt, /* operands */
1839               UInt rM      /* only for debug printing */
1840            )
1841{
1842   if (shift_amt == 0) {
1843      // conceptually a 32-bit shift, however:
1844      // res  = 0
1845      // newC = Rm[31]
1846      if (newC) {
1847         assign( *newC,
1848                 binop(Iop_And32,
1849                       binop(Iop_Shr32, mkexpr(rMt), mkU8(31)),
1850                       mkU32(1)));
1851      }
1852      assign( *res, mkU32(0) );
1853      DIS(buf, "r%u, LSR #0(a.k.a. 32)", rM);
1854   } else {
1855      // shift in range 1..31
1856      // res  = Rm >>u shift_amt
1857      // newC = Rm[shift_amt - 1]
1858      vassert(shift_amt >= 1 && shift_amt <= 31);
1859      if (newC) {
1860         assign( *newC,
1861                 binop(Iop_And32,
1862                       binop(Iop_Shr32, mkexpr(rMt),
1863                                        mkU8(shift_amt - 1)),
1864                       mkU32(1)));
1865      }
1866      assign( *res,
1867              binop(Iop_Shr32, mkexpr(rMt), mkU8(shift_amt)) );
1868      DIS(buf, "r%u, LSR #%u", rM, shift_amt);
1869   }
1870}
1871
1872
1873static void compute_result_and_C_after_LSR_by_reg (
1874               /*OUT*/HChar* buf,
1875               IRTemp* res,
1876               IRTemp* newC,
1877               IRTemp rMt, IRTemp rSt,  /* operands */
1878               UInt rM,    UInt rS      /* only for debug printing */
1879            )
1880{
1881   // shift right in range 0 .. 255
1882   // amt = rS & 255
1883   // res  = amt < 32 ?  Rm >>u amt  : 0
1884   // newC = amt == 0     ? oldC  :
1885   //        amt in 1..32 ?  Rm[amt-1]  : 0
1886   IRTemp amtT = newTemp(Ity_I32);
1887   assign( amtT, binop(Iop_And32, mkexpr(rSt), mkU32(255)) );
1888   if (newC) {
1889      /* mux0X(amt == 0,
1890               mux0X(amt < 32,
1891                     0,
1892                     Rm[(amt-1) & 31]),
1893               oldC)
1894      */
1895      IRTemp oldC = newTemp(Ity_I32);
1896      assign(oldC, mk_armg_calculate_flag_c() );
1897      assign(
1898         *newC,
1899         IRExpr_Mux0X(
1900            unop(Iop_1Uto8,
1901                 binop(Iop_CmpEQ32, mkexpr(amtT), mkU32(0))),
1902            IRExpr_Mux0X(
1903               unop(Iop_1Uto8,
1904                    binop(Iop_CmpLE32U, mkexpr(amtT), mkU32(32))),
1905               mkU32(0),
1906               binop(Iop_And32,
1907                     binop(Iop_Shr32,
1908                           mkexpr(rMt),
1909                           unop(Iop_32to8,
1910                                binop(Iop_And32,
1911                                      binop(Iop_Sub32,
1912                                            mkexpr(amtT),
1913                                            mkU32(1)),
1914                                      mkU32(31)
1915                                )
1916                           )
1917                     ),
1918                     mkU32(1)
1919               )
1920            ),
1921            mkexpr(oldC)
1922         )
1923      );
1924   }
1925   // (Rm >>u (Rs & 31))  &  (((Rs & 255) - 32) >>s 31)
1926   // Lhs of the & limits the shift to 31 bits, so as to
1927   // give known IR semantics.  Rhs of the & is all 1s for
1928   // Rs <= 31 and all 0s for Rs >= 32.
1929   assign(
1930      *res,
1931      binop(
1932         Iop_And32,
1933         binop(Iop_Shr32,
1934               mkexpr(rMt),
1935               unop(Iop_32to8,
1936                    binop(Iop_And32, mkexpr(rSt), mkU32(31)))),
1937         binop(Iop_Sar32,
1938               binop(Iop_Sub32,
1939                     mkexpr(amtT),
1940                     mkU32(32)),
1941               mkU8(31))));
1942    DIS(buf, "r%u, LSR r%u", rM, rS);
1943}
1944
1945
1946static void compute_result_and_C_after_ASR_by_imm5 (
1947               /*OUT*/HChar* buf,
1948               IRTemp* res,
1949               IRTemp* newC,
1950               IRTemp rMt, UInt shift_amt, /* operands */
1951               UInt rM      /* only for debug printing */
1952            )
1953{
1954   if (shift_amt == 0) {
1955      // conceptually a 32-bit shift, however:
1956      // res  = Rm >>s 31
1957      // newC = Rm[31]
1958      if (newC) {
1959         assign( *newC,
1960                 binop(Iop_And32,
1961                       binop(Iop_Shr32, mkexpr(rMt), mkU8(31)),
1962                       mkU32(1)));
1963      }
1964      assign( *res, binop(Iop_Sar32, mkexpr(rMt), mkU8(31)) );
1965      DIS(buf, "r%u, ASR #0(a.k.a. 32)", rM);
1966   } else {
1967      // shift in range 1..31
1968      // res = Rm >>s shift_amt
1969      // newC = Rm[shift_amt - 1]
1970      vassert(shift_amt >= 1 && shift_amt <= 31);
1971      if (newC) {
1972         assign( *newC,
1973                 binop(Iop_And32,
1974                       binop(Iop_Shr32, mkexpr(rMt),
1975                                        mkU8(shift_amt - 1)),
1976                       mkU32(1)));
1977      }
1978      assign( *res,
1979              binop(Iop_Sar32, mkexpr(rMt), mkU8(shift_amt)) );
1980      DIS(buf, "r%u, ASR #%u", rM, shift_amt);
1981   }
1982}
1983
1984
1985static void compute_result_and_C_after_ASR_by_reg (
1986               /*OUT*/HChar* buf,
1987               IRTemp* res,
1988               IRTemp* newC,
1989               IRTemp rMt, IRTemp rSt,  /* operands */
1990               UInt rM,    UInt rS      /* only for debug printing */
1991            )
1992{
1993   // arithmetic shift right in range 0 .. 255
1994   // amt = rS & 255
1995   // res  = amt < 32 ?  Rm >>s amt  : Rm >>s 31
1996   // newC = amt == 0     ? oldC  :
1997   //        amt in 1..32 ?  Rm[amt-1]  : Rm[31]
1998   IRTemp amtT = newTemp(Ity_I32);
1999   assign( amtT, binop(Iop_And32, mkexpr(rSt), mkU32(255)) );
2000   if (newC) {
2001      /* mux0X(amt == 0,
2002               mux0X(amt < 32,
2003                     Rm[31],
2004                     Rm[(amt-1) & 31])
2005               oldC)
2006      */
2007      IRTemp oldC = newTemp(Ity_I32);
2008      assign(oldC, mk_armg_calculate_flag_c() );
2009      assign(
2010         *newC,
2011         IRExpr_Mux0X(
2012            unop(Iop_1Uto8,
2013                 binop(Iop_CmpEQ32, mkexpr(amtT), mkU32(0))),
2014            IRExpr_Mux0X(
2015               unop(Iop_1Uto8,
2016                    binop(Iop_CmpLE32U, mkexpr(amtT), mkU32(32))),
2017               binop(Iop_And32,
2018                     binop(Iop_Shr32,
2019                           mkexpr(rMt),
2020                           mkU8(31)
2021                     ),
2022                     mkU32(1)
2023               ),
2024               binop(Iop_And32,
2025                     binop(Iop_Shr32,
2026                           mkexpr(rMt),
2027                           unop(Iop_32to8,
2028                                binop(Iop_And32,
2029                                      binop(Iop_Sub32,
2030                                            mkexpr(amtT),
2031                                            mkU32(1)),
2032                                      mkU32(31)
2033                                )
2034                           )
2035                     ),
2036                     mkU32(1)
2037               )
2038            ),
2039            mkexpr(oldC)
2040         )
2041      );
2042   }
2043   // (Rm >>s (amt <u 32 ? amt : 31))
2044   assign(
2045      *res,
2046      binop(
2047         Iop_Sar32,
2048         mkexpr(rMt),
2049         unop(
2050            Iop_32to8,
2051            IRExpr_Mux0X(
2052               unop(
2053                 Iop_1Uto8,
2054                 binop(Iop_CmpLT32U, mkexpr(amtT), mkU32(32))),
2055               mkU32(31),
2056               mkexpr(amtT)))));
2057    DIS(buf, "r%u, ASR r%u", rM, rS);
2058}
2059
2060
2061static void compute_result_and_C_after_ROR_by_reg (
2062               /*OUT*/HChar* buf,
2063               IRTemp* res,
2064               IRTemp* newC,
2065               IRTemp rMt, IRTemp rSt,  /* operands */
2066               UInt rM,    UInt rS      /* only for debug printing */
2067            )
2068{
2069   // rotate right in range 0 .. 255
2070   // amt = rS & 255
2071   // shop =  Rm `ror` (amt & 31)
2072   // shco =  amt == 0 ? oldC : Rm[(amt-1) & 31]
2073   IRTemp amtT = newTemp(Ity_I32);
2074   assign( amtT, binop(Iop_And32, mkexpr(rSt), mkU32(255)) );
2075   IRTemp amt5T = newTemp(Ity_I32);
2076   assign( amt5T, binop(Iop_And32, mkexpr(rSt), mkU32(31)) );
2077   IRTemp oldC = newTemp(Ity_I32);
2078   assign(oldC, mk_armg_calculate_flag_c() );
2079   if (newC) {
2080      assign(
2081         *newC,
2082         IRExpr_Mux0X(
2083            unop(Iop_32to8, mkexpr(amtT)),
2084            mkexpr(oldC),
2085            binop(Iop_And32,
2086                  binop(Iop_Shr32,
2087                        mkexpr(rMt),
2088                        unop(Iop_32to8,
2089                             binop(Iop_And32,
2090                                   binop(Iop_Sub32,
2091                                         mkexpr(amtT),
2092                                         mkU32(1)
2093                                   ),
2094                                   mkU32(31)
2095                             )
2096                        )
2097                  ),
2098                  mkU32(1)
2099            )
2100         )
2101      );
2102   }
2103   assign(
2104      *res,
2105      IRExpr_Mux0X(
2106         unop(Iop_32to8, mkexpr(amt5T)), mkexpr(rMt),
2107         binop(Iop_Or32,
2108               binop(Iop_Shr32,
2109                     mkexpr(rMt),
2110                     unop(Iop_32to8, mkexpr(amt5T))
2111               ),
2112               binop(Iop_Shl32,
2113                     mkexpr(rMt),
2114                     unop(Iop_32to8,
2115                          binop(Iop_Sub32, mkU32(32), mkexpr(amt5T))
2116                     )
2117               )
2118         )
2119      )
2120   );
2121   DIS(buf, "r%u, ROR r#%u", rM, rS);
2122}
2123
2124
2125/* Generate an expression corresponding to the immediate-shift case of
2126   a shifter operand.  This is used both for ARM and Thumb2.
2127
2128   Bind it to a temporary, and return that via *res.  If newC is
2129   non-NULL, also compute a value for the shifter's carry out (in the
2130   LSB of a word), bind it to a temporary, and return that via *shco.
2131
2132   Generates GETs from the guest state and is therefore not safe to
2133   use once we start doing PUTs to it, for any given instruction.
2134
2135   'how' is encoded thusly:
2136      00b LSL,  01b LSR,  10b ASR,  11b ROR
2137   Most but not all ARM and Thumb integer insns use this encoding.
2138   Be careful to ensure the right value is passed here.
2139*/
2140static void compute_result_and_C_after_shift_by_imm5 (
2141               /*OUT*/HChar* buf,
2142               /*OUT*/IRTemp* res,
2143               /*OUT*/IRTemp* newC,
2144               IRTemp  rMt,       /* reg to shift */
2145               UInt    how,       /* what kind of shift */
2146               UInt    shift_amt, /* shift amount (0..31) */
2147               UInt    rM         /* only for debug printing */
2148            )
2149{
2150   vassert(shift_amt < 32);
2151   vassert(how < 4);
2152
2153   switch (how) {
2154
2155      case 0:
2156         compute_result_and_C_after_LSL_by_imm5(
2157            buf, res, newC, rMt, shift_amt, rM
2158         );
2159         break;
2160
2161      case 1:
2162         compute_result_and_C_after_LSR_by_imm5(
2163            buf, res, newC, rMt, shift_amt, rM
2164         );
2165         break;
2166
2167      case 2:
2168         compute_result_and_C_after_ASR_by_imm5(
2169            buf, res, newC, rMt, shift_amt, rM
2170         );
2171         break;
2172
2173      case 3:
2174         if (shift_amt == 0) {
2175            IRTemp oldcT = newTemp(Ity_I32);
2176            // rotate right 1 bit through carry (?)
2177            // RRX -- described at ARM ARM A5-17
2178            // res  = (oldC << 31) | (Rm >>u 1)
2179            // newC = Rm[0]
2180            if (newC) {
2181               assign( *newC,
2182                       binop(Iop_And32, mkexpr(rMt), mkU32(1)));
2183            }
2184            assign( oldcT, mk_armg_calculate_flag_c() );
2185            assign( *res,
2186                    binop(Iop_Or32,
2187                          binop(Iop_Shl32, mkexpr(oldcT), mkU8(31)),
2188                          binop(Iop_Shr32, mkexpr(rMt), mkU8(1))) );
2189            DIS(buf, "r%u, RRX", rM);
2190         } else {
2191            // rotate right in range 1..31
2192            // res  = Rm `ror` shift_amt
2193            // newC = Rm[shift_amt - 1]
2194            vassert(shift_amt >= 1 && shift_amt <= 31);
2195            if (newC) {
2196               assign( *newC,
2197                       binop(Iop_And32,
2198                             binop(Iop_Shr32, mkexpr(rMt),
2199                                              mkU8(shift_amt - 1)),
2200                             mkU32(1)));
2201            }
2202            assign( *res,
2203                    binop(Iop_Or32,
2204                          binop(Iop_Shr32, mkexpr(rMt), mkU8(shift_amt)),
2205                          binop(Iop_Shl32, mkexpr(rMt),
2206                                           mkU8(32-shift_amt))));
2207            DIS(buf, "r%u, ROR #%u", rM, shift_amt);
2208         }
2209         break;
2210
2211      default:
2212         /*NOTREACHED*/
2213         vassert(0);
2214   }
2215}
2216
2217
2218/* Generate an expression corresponding to the register-shift case of
2219   a shifter operand.  This is used both for ARM and Thumb2.
2220
2221   Bind it to a temporary, and return that via *res.  If newC is
2222   non-NULL, also compute a value for the shifter's carry out (in the
2223   LSB of a word), bind it to a temporary, and return that via *shco.
2224
2225   Generates GETs from the guest state and is therefore not safe to
2226   use once we start doing PUTs to it, for any given instruction.
2227
2228   'how' is encoded thusly:
2229      00b LSL,  01b LSR,  10b ASR,  11b ROR
2230   Most but not all ARM and Thumb integer insns use this encoding.
2231   Be careful to ensure the right value is passed here.
2232*/
2233static void compute_result_and_C_after_shift_by_reg (
2234               /*OUT*/HChar*  buf,
2235               /*OUT*/IRTemp* res,
2236               /*OUT*/IRTemp* newC,
2237               IRTemp  rMt,       /* reg to shift */
2238               UInt    how,       /* what kind of shift */
2239               IRTemp  rSt,       /* shift amount */
2240               UInt    rM,        /* only for debug printing */
2241               UInt    rS         /* only for debug printing */
2242            )
2243{
2244   vassert(how < 4);
2245   switch (how) {
2246      case 0: { /* LSL */
2247         compute_result_and_C_after_LSL_by_reg(
2248            buf, res, newC, rMt, rSt, rM, rS
2249         );
2250         break;
2251      }
2252      case 1: { /* LSR */
2253         compute_result_and_C_after_LSR_by_reg(
2254            buf, res, newC, rMt, rSt, rM, rS
2255         );
2256         break;
2257      }
2258      case 2: { /* ASR */
2259         compute_result_and_C_after_ASR_by_reg(
2260            buf, res, newC, rMt, rSt, rM, rS
2261         );
2262         break;
2263      }
2264      case 3: { /* ROR */
2265         compute_result_and_C_after_ROR_by_reg(
2266             buf, res, newC, rMt, rSt, rM, rS
2267         );
2268         break;
2269      }
2270      default:
2271         /*NOTREACHED*/
2272         vassert(0);
2273   }
2274}
2275
2276
2277/* Generate an expression corresponding to a shifter_operand, bind it
2278   to a temporary, and return that via *shop.  If shco is non-NULL,
2279   also compute a value for the shifter's carry out (in the LSB of a
2280   word), bind it to a temporary, and return that via *shco.
2281
2282   If for some reason we can't come up with a shifter operand (missing
2283   case?  not really a shifter operand?) return False.
2284
2285   Generates GETs from the guest state and is therefore not safe to
2286   use once we start doing PUTs to it, for any given instruction.
2287
2288   For ARM insns only; not for Thumb.
2289*/
2290static Bool mk_shifter_operand ( UInt insn_25, UInt insn_11_0,
2291                                 /*OUT*/IRTemp* shop,
2292                                 /*OUT*/IRTemp* shco,
2293                                 /*OUT*/HChar* buf )
2294{
2295   UInt insn_4 = (insn_11_0 >> 4) & 1;
2296   UInt insn_7 = (insn_11_0 >> 7) & 1;
2297   vassert(insn_25 <= 0x1);
2298   vassert(insn_11_0 <= 0xFFF);
2299
2300   vassert(shop && *shop == IRTemp_INVALID);
2301   *shop = newTemp(Ity_I32);
2302
2303   if (shco) {
2304      vassert(*shco == IRTemp_INVALID);
2305      *shco = newTemp(Ity_I32);
2306   }
2307
2308   /* 32-bit immediate */
2309
2310   if (insn_25 == 1) {
2311      /* immediate: (7:0) rotated right by 2 * (11:8) */
2312      UInt imm = (insn_11_0 >> 0) & 0xFF;
2313      UInt rot = 2 * ((insn_11_0 >> 8) & 0xF);
2314      vassert(rot <= 30);
2315      imm = ROR32(imm, rot);
2316      if (shco) {
2317         if (rot == 0) {
2318            assign( *shco, mk_armg_calculate_flag_c() );
2319         } else {
2320            assign( *shco, mkU32( (imm >> 31) & 1 ) );
2321         }
2322      }
2323      DIS(buf, "#0x%x", imm);
2324      assign( *shop, mkU32(imm) );
2325      return True;
2326   }
2327
2328   /* Shift/rotate by immediate */
2329
2330   if (insn_25 == 0 && insn_4 == 0) {
2331      /* Rm (3:0) shifted (6:5) by immediate (11:7) */
2332      UInt shift_amt = (insn_11_0 >> 7) & 0x1F;
2333      UInt rM        = (insn_11_0 >> 0) & 0xF;
2334      UInt how       = (insn_11_0 >> 5) & 3;
2335      /* how: 00 = Shl, 01 = Shr, 10 = Sar, 11 = Ror */
2336      IRTemp rMt = newTemp(Ity_I32);
2337      assign(rMt, getIRegA(rM));
2338
2339      vassert(shift_amt <= 31);
2340
2341      compute_result_and_C_after_shift_by_imm5(
2342         buf, shop, shco, rMt, how, shift_amt, rM
2343      );
2344      return True;
2345   }
2346
2347   /* Shift/rotate by register */
2348   if (insn_25 == 0 && insn_4 == 1) {
2349      /* Rm (3:0) shifted (6:5) by Rs (11:8) */
2350      UInt rM  = (insn_11_0 >> 0) & 0xF;
2351      UInt rS  = (insn_11_0 >> 8) & 0xF;
2352      UInt how = (insn_11_0 >> 5) & 3;
2353      /* how: 00 = Shl, 01 = Shr, 10 = Sar, 11 = Ror */
2354      IRTemp rMt = newTemp(Ity_I32);
2355      IRTemp rSt = newTemp(Ity_I32);
2356
2357      if (insn_7 == 1)
2358         return False; /* not really a shifter operand */
2359
2360      assign(rMt, getIRegA(rM));
2361      assign(rSt, getIRegA(rS));
2362
2363      compute_result_and_C_after_shift_by_reg(
2364         buf, shop, shco, rMt, how, rSt, rM, rS
2365      );
2366      return True;
2367   }
2368
2369   vex_printf("mk_shifter_operand(0x%x,0x%x)\n", insn_25, insn_11_0 );
2370   return False;
2371}
2372
2373
2374/* ARM only */
2375static
2376IRExpr* mk_EA_reg_plusminus_imm12 ( UInt rN, UInt bU, UInt imm12,
2377                                    /*OUT*/HChar* buf )
2378{
2379   vassert(rN < 16);
2380   vassert(bU < 2);
2381   vassert(imm12 < 0x1000);
2382   UChar opChar = bU == 1 ? '+' : '-';
2383   DIS(buf, "[r%u, #%c%u]", rN, opChar, imm12);
2384   return
2385      binop( (bU == 1 ? Iop_Add32 : Iop_Sub32),
2386             getIRegA(rN),
2387             mkU32(imm12) );
2388}
2389
2390
2391/* ARM only.
2392   NB: This is "DecodeImmShift" in newer versions of the the ARM ARM.
2393*/
2394static
2395IRExpr* mk_EA_reg_plusminus_shifted_reg ( UInt rN, UInt bU, UInt rM,
2396                                          UInt sh2, UInt imm5,
2397                                          /*OUT*/HChar* buf )
2398{
2399   vassert(rN < 16);
2400   vassert(bU < 2);
2401   vassert(rM < 16);
2402   vassert(sh2 < 4);
2403   vassert(imm5 < 32);
2404   UChar   opChar = bU == 1 ? '+' : '-';
2405   IRExpr* index  = NULL;
2406   switch (sh2) {
2407      case 0: /* LSL */
2408         /* imm5 can be in the range 0 .. 31 inclusive. */
2409         index = binop(Iop_Shl32, getIRegA(rM), mkU8(imm5));
2410         DIS(buf, "[r%u, %c r%u LSL #%u]", rN, opChar, rM, imm5);
2411         break;
2412      case 1: /* LSR */
2413         if (imm5 == 0) {
2414            index = mkU32(0);
2415            vassert(0); // ATC
2416         } else {
2417            index = binop(Iop_Shr32, getIRegA(rM), mkU8(imm5));
2418         }
2419         DIS(buf, "[r%u, %cr%u, LSR #%u]",
2420                  rN, opChar, rM, imm5 == 0 ? 32 : imm5);
2421         break;
2422      case 2: /* ASR */
2423         /* Doesn't this just mean that the behaviour with imm5 == 0
2424            is the same as if it had been 31 ? */
2425         if (imm5 == 0) {
2426            index = binop(Iop_Sar32, getIRegA(rM), mkU8(31));
2427            vassert(0); // ATC
2428         } else {
2429            index = binop(Iop_Sar32, getIRegA(rM), mkU8(imm5));
2430         }
2431         DIS(buf, "[r%u, %cr%u, ASR #%u]",
2432                  rN, opChar, rM, imm5 == 0 ? 32 : imm5);
2433         break;
2434      case 3: /* ROR or RRX */
2435         if (imm5 == 0) {
2436            IRTemp rmT    = newTemp(Ity_I32);
2437            IRTemp cflagT = newTemp(Ity_I32);
2438            assign(rmT, getIRegA(rM));
2439            assign(cflagT, mk_armg_calculate_flag_c());
2440            index = binop(Iop_Or32,
2441                          binop(Iop_Shl32, mkexpr(cflagT), mkU8(31)),
2442                          binop(Iop_Shr32, mkexpr(rmT), mkU8(1)));
2443            DIS(buf, "[r%u, %cr%u, RRX]", rN, opChar, rM);
2444         } else {
2445            IRTemp rmT = newTemp(Ity_I32);
2446            assign(rmT, getIRegA(rM));
2447            vassert(imm5 >= 1 && imm5 <= 31);
2448            index = binop(Iop_Or32,
2449                          binop(Iop_Shl32, mkexpr(rmT), mkU8(32-imm5)),
2450                          binop(Iop_Shr32, mkexpr(rmT), mkU8(imm5)));
2451            DIS(buf, "[r%u, %cr%u, ROR #%u]", rN, opChar, rM, imm5);
2452         }
2453         break;
2454      default:
2455         vassert(0);
2456   }
2457   vassert(index);
2458   return binop(bU == 1 ? Iop_Add32 : Iop_Sub32,
2459                getIRegA(rN), index);
2460}
2461
2462
2463/* ARM only */
2464static
2465IRExpr* mk_EA_reg_plusminus_imm8 ( UInt rN, UInt bU, UInt imm8,
2466                                   /*OUT*/HChar* buf )
2467{
2468   vassert(rN < 16);
2469   vassert(bU < 2);
2470   vassert(imm8 < 0x100);
2471   UChar opChar = bU == 1 ? '+' : '-';
2472   DIS(buf, "[r%u, #%c%u]", rN, opChar, imm8);
2473   return
2474      binop( (bU == 1 ? Iop_Add32 : Iop_Sub32),
2475             getIRegA(rN),
2476             mkU32(imm8) );
2477}
2478
2479
2480/* ARM only */
2481static
2482IRExpr* mk_EA_reg_plusminus_reg ( UInt rN, UInt bU, UInt rM,
2483                                  /*OUT*/HChar* buf )
2484{
2485   vassert(rN < 16);
2486   vassert(bU < 2);
2487   vassert(rM < 16);
2488   UChar   opChar = bU == 1 ? '+' : '-';
2489   IRExpr* index  = getIRegA(rM);
2490   DIS(buf, "[r%u, %c r%u]", rN, opChar, rM);
2491   return binop(bU == 1 ? Iop_Add32 : Iop_Sub32,
2492                getIRegA(rN), index);
2493}
2494
2495
2496/* irRes :: Ity_I32 holds a floating point comparison result encoded
2497   as an IRCmpF64Result.  Generate code to convert it to an
2498   ARM-encoded (N,Z,C,V) group in the lowest 4 bits of an I32 value.
2499   Assign a new temp to hold that value, and return the temp. */
2500static
2501IRTemp mk_convert_IRCmpF64Result_to_NZCV ( IRTemp irRes )
2502{
2503   IRTemp ix       = newTemp(Ity_I32);
2504   IRTemp termL    = newTemp(Ity_I32);
2505   IRTemp termR    = newTemp(Ity_I32);
2506   IRTemp nzcv     = newTemp(Ity_I32);
2507
2508   /* This is where the fun starts.  We have to convert 'irRes' from
2509      an IR-convention return result (IRCmpF64Result) to an
2510      ARM-encoded (N,Z,C,V) group.  The final result is in the bottom
2511      4 bits of 'nzcv'. */
2512   /* Map compare result from IR to ARM(nzcv) */
2513   /*
2514      FP cmp result | IR   | ARM(nzcv)
2515      --------------------------------
2516      UN              0x45   0011
2517      LT              0x01   1000
2518      GT              0x00   0010
2519      EQ              0x40   0110
2520   */
2521   /* Now since you're probably wondering WTF ..
2522
2523      ix fishes the useful bits out of the IR value, bits 6 and 0, and
2524      places them side by side, giving a number which is 0, 1, 2 or 3.
2525
2526      termL is a sequence cooked up by GNU superopt.  It converts ix
2527         into an almost correct value NZCV value (incredibly), except
2528         for the case of UN, where it produces 0100 instead of the
2529         required 0011.
2530
2531      termR is therefore a correction term, also computed from ix.  It
2532         is 1 in the UN case and 0 for LT, GT and UN.  Hence, to get
2533         the final correct value, we subtract termR from termL.
2534
2535      Don't take my word for it.  There's a test program at the bottom
2536      of this file, to try this out with.
2537   */
2538   assign(
2539      ix,
2540      binop(Iop_Or32,
2541            binop(Iop_And32,
2542                  binop(Iop_Shr32, mkexpr(irRes), mkU8(5)),
2543                  mkU32(3)),
2544            binop(Iop_And32, mkexpr(irRes), mkU32(1))));
2545
2546   assign(
2547      termL,
2548      binop(Iop_Add32,
2549            binop(Iop_Shr32,
2550                  binop(Iop_Sub32,
2551                        binop(Iop_Shl32,
2552                              binop(Iop_Xor32, mkexpr(ix), mkU32(1)),
2553                              mkU8(30)),
2554                        mkU32(1)),
2555                  mkU8(29)),
2556            mkU32(1)));
2557
2558   assign(
2559      termR,
2560      binop(Iop_And32,
2561            binop(Iop_And32,
2562                  mkexpr(ix),
2563                  binop(Iop_Shr32, mkexpr(ix), mkU8(1))),
2564            mkU32(1)));
2565
2566   assign(nzcv, binop(Iop_Sub32, mkexpr(termL), mkexpr(termR)));
2567   return nzcv;
2568}
2569
2570
2571/* Thumb32 only.  This is "ThumbExpandImm" in the ARM ARM.  If
2572   updatesC is non-NULL, a boolean is written to it indicating whether
2573   or not the C flag is updated, as per ARM ARM "ThumbExpandImm_C".
2574*/
2575static UInt thumbExpandImm ( Bool* updatesC,
2576                             UInt imm1, UInt imm3, UInt imm8 )
2577{
2578   vassert(imm1 < (1<<1));
2579   vassert(imm3 < (1<<3));
2580   vassert(imm8 < (1<<8));
2581   UInt i_imm3_a = (imm1 << 4) | (imm3 << 1) | ((imm8 >> 7) & 1);
2582   UInt abcdefgh = imm8;
2583   UInt lbcdefgh = imm8 | 0x80;
2584   if (updatesC) {
2585      *updatesC = i_imm3_a >= 8;
2586   }
2587   switch (i_imm3_a) {
2588      case 0: case 1:
2589         return abcdefgh;
2590      case 2: case 3:
2591         return (abcdefgh << 16) | abcdefgh;
2592      case 4: case 5:
2593         return (abcdefgh << 24) | (abcdefgh << 8);
2594      case 6: case 7:
2595         return (abcdefgh << 24) | (abcdefgh << 16)
2596                | (abcdefgh << 8) | abcdefgh;
2597      case 8 ... 31:
2598         return lbcdefgh << (32 - i_imm3_a);
2599      default:
2600         break;
2601   }
2602   /*NOTREACHED*/vassert(0);
2603}
2604
2605
2606/* Version of thumbExpandImm where we simply feed it the
2607   instruction halfwords (the lowest addressed one is I0). */
2608static UInt thumbExpandImm_from_I0_I1 ( Bool* updatesC,
2609                                        UShort i0s, UShort i1s )
2610{
2611   UInt i0    = (UInt)i0s;
2612   UInt i1    = (UInt)i1s;
2613   UInt imm1  = SLICE_UInt(i0,10,10);
2614   UInt imm3  = SLICE_UInt(i1,14,12);
2615   UInt imm8  = SLICE_UInt(i1,7,0);
2616   return thumbExpandImm(updatesC, imm1, imm3, imm8);
2617}
2618
2619
2620/* Thumb16 only.  Given the firstcond and mask fields from an IT
2621   instruction, compute the 32-bit ITSTATE value implied, as described
2622   in libvex_guest_arm.h.  This is not the ARM ARM representation.
2623   Also produce the t/e chars for the 2nd, 3rd, 4th insns, for
2624   disassembly printing.  Returns False if firstcond or mask
2625   denote something invalid.
2626
2627   The number and conditions for the instructions to be
2628   conditionalised depend on firstcond and mask:
2629
2630   mask      cond 1    cond 2      cond 3      cond 4
2631
2632   1000      fc[3:0]
2633   x100      fc[3:0]   fc[3:1]:x
2634   xy10      fc[3:0]   fc[3:1]:x   fc[3:1]:y
2635   xyz1      fc[3:0]   fc[3:1]:x   fc[3:1]:y   fc[3:1]:z
2636
2637   The condition fields are assembled in *itstate backwards (cond 4 at
2638   the top, cond 1 at the bottom).  Conditions are << 4'd and then
2639   ^0xE'd, and those fields that correspond to instructions in the IT
2640   block are tagged with a 1 bit.
2641*/
2642static Bool compute_ITSTATE ( /*OUT*/UInt*  itstate,
2643                              /*OUT*/UChar* ch1,
2644                              /*OUT*/UChar* ch2,
2645                              /*OUT*/UChar* ch3,
2646                              UInt firstcond, UInt mask )
2647{
2648   vassert(firstcond <= 0xF);
2649   vassert(mask <= 0xF);
2650   *itstate = 0;
2651   *ch1 = *ch2 = *ch3 = '.';
2652   if (mask == 0)
2653      return False; /* the logic below actually ensures this anyway,
2654                       but clearer to make it explicit. */
2655   if (firstcond == 0xF)
2656      return False; /* NV is not allowed */
2657   if (firstcond == 0xE && popcount32(mask) != 1)
2658      return False; /* if firstcond is AL then all the rest must be too */
2659
2660   UInt m3 = (mask >> 3) & 1;
2661   UInt m2 = (mask >> 2) & 1;
2662   UInt m1 = (mask >> 1) & 1;
2663   UInt m0 = (mask >> 0) & 1;
2664
2665   UInt fc = (firstcond << 4) | 1/*in-IT-block*/;
2666   UInt ni = (0xE/*AL*/ << 4) | 0/*not-in-IT-block*/;
2667
2668   if (m3 == 1 && (m2|m1|m0) == 0) {
2669      *itstate = (ni << 24) | (ni << 16) | (ni << 8) | fc;
2670      *itstate ^= 0xE0E0E0E0;
2671      return True;
2672   }
2673
2674   if (m2 == 1 && (m1|m0) == 0) {
2675      *itstate = (ni << 24) | (ni << 16) | (setbit32(fc, 4, m3) << 8) | fc;
2676      *itstate ^= 0xE0E0E0E0;
2677      *ch1 = m3 == (firstcond & 1) ? 't' : 'e';
2678      return True;
2679   }
2680
2681   if (m1 == 1 && m0 == 0) {
2682      *itstate = (ni << 24)
2683                 | (setbit32(fc, 4, m2) << 16)
2684                 | (setbit32(fc, 4, m3) << 8) | fc;
2685      *itstate ^= 0xE0E0E0E0;
2686      *ch1 = m3 == (firstcond & 1) ? 't' : 'e';
2687      *ch2 = m2 == (firstcond & 1) ? 't' : 'e';
2688      return True;
2689   }
2690
2691   if (m0 == 1) {
2692      *itstate = (setbit32(fc, 4, m1) << 24)
2693                 | (setbit32(fc, 4, m2) << 16)
2694                 | (setbit32(fc, 4, m3) << 8) | fc;
2695      *itstate ^= 0xE0E0E0E0;
2696      *ch1 = m3 == (firstcond & 1) ? 't' : 'e';
2697      *ch2 = m2 == (firstcond & 1) ? 't' : 'e';
2698      *ch3 = m1 == (firstcond & 1) ? 't' : 'e';
2699      return True;
2700   }
2701
2702   return False;
2703}
2704
2705
2706/* Generate IR to do 32-bit bit reversal, a la Hacker's Delight
2707   Chapter 7 Section 1. */
2708static IRTemp gen_BITREV ( IRTemp x0 )
2709{
2710   IRTemp x1 = newTemp(Ity_I32);
2711   IRTemp x2 = newTemp(Ity_I32);
2712   IRTemp x3 = newTemp(Ity_I32);
2713   IRTemp x4 = newTemp(Ity_I32);
2714   IRTemp x5 = newTemp(Ity_I32);
2715   UInt   c1 = 0x55555555;
2716   UInt   c2 = 0x33333333;
2717   UInt   c3 = 0x0F0F0F0F;
2718   UInt   c4 = 0x00FF00FF;
2719   UInt   c5 = 0x0000FFFF;
2720   assign(x1,
2721          binop(Iop_Or32,
2722                binop(Iop_Shl32,
2723                      binop(Iop_And32, mkexpr(x0), mkU32(c1)),
2724                      mkU8(1)),
2725                binop(Iop_Shr32,
2726                      binop(Iop_And32, mkexpr(x0), mkU32(~c1)),
2727                      mkU8(1))
2728   ));
2729   assign(x2,
2730          binop(Iop_Or32,
2731                binop(Iop_Shl32,
2732                      binop(Iop_And32, mkexpr(x1), mkU32(c2)),
2733                      mkU8(2)),
2734                binop(Iop_Shr32,
2735                      binop(Iop_And32, mkexpr(x1), mkU32(~c2)),
2736                      mkU8(2))
2737   ));
2738   assign(x3,
2739          binop(Iop_Or32,
2740                binop(Iop_Shl32,
2741                      binop(Iop_And32, mkexpr(x2), mkU32(c3)),
2742                      mkU8(4)),
2743                binop(Iop_Shr32,
2744                      binop(Iop_And32, mkexpr(x2), mkU32(~c3)),
2745                      mkU8(4))
2746   ));
2747   assign(x4,
2748          binop(Iop_Or32,
2749                binop(Iop_Shl32,
2750                      binop(Iop_And32, mkexpr(x3), mkU32(c4)),
2751                      mkU8(8)),
2752                binop(Iop_Shr32,
2753                      binop(Iop_And32, mkexpr(x3), mkU32(~c4)),
2754                      mkU8(8))
2755   ));
2756   assign(x5,
2757          binop(Iop_Or32,
2758                binop(Iop_Shl32,
2759                      binop(Iop_And32, mkexpr(x4), mkU32(c5)),
2760                      mkU8(16)),
2761                binop(Iop_Shr32,
2762                      binop(Iop_And32, mkexpr(x4), mkU32(~c5)),
2763                      mkU8(16))
2764   ));
2765   return x5;
2766}
2767
2768
2769/* Generate IR to do rearrange bytes 3:2:1:0 in a word in to the order
2770   0:1:2:3 (aka byte-swap). */
2771static IRTemp gen_REV ( IRTemp arg )
2772{
2773   IRTemp res = newTemp(Ity_I32);
2774   assign(res,
2775          binop(Iop_Or32,
2776                binop(Iop_Shl32, mkexpr(arg), mkU8(24)),
2777          binop(Iop_Or32,
2778                binop(Iop_And32, binop(Iop_Shl32, mkexpr(arg), mkU8(8)),
2779                                 mkU32(0x00FF0000)),
2780          binop(Iop_Or32,
2781                binop(Iop_And32, binop(Iop_Shr32, mkexpr(arg), mkU8(8)),
2782                                       mkU32(0x0000FF00)),
2783                binop(Iop_And32, binop(Iop_Shr32, mkexpr(arg), mkU8(24)),
2784                                       mkU32(0x000000FF) )
2785   ))));
2786   return res;
2787}
2788
2789
2790/* Generate IR to do rearrange bytes 3:2:1:0 in a word in to the order
2791   2:3:0:1 (swap within lo and hi halves). */
2792static IRTemp gen_REV16 ( IRTemp arg )
2793{
2794   IRTemp res = newTemp(Ity_I32);
2795   assign(res,
2796          binop(Iop_Or32,
2797                binop(Iop_And32,
2798                      binop(Iop_Shl32, mkexpr(arg), mkU8(8)),
2799                      mkU32(0xFF00FF00)),
2800                binop(Iop_And32,
2801                      binop(Iop_Shr32, mkexpr(arg), mkU8(8)),
2802                      mkU32(0x00FF00FF))));
2803   return res;
2804}
2805
2806
2807/*------------------------------------------------------------*/
2808/*--- Advanced SIMD (NEON) instructions                    ---*/
2809/*------------------------------------------------------------*/
2810
2811/*------------------------------------------------------------*/
2812/*--- NEON data processing                                 ---*/
2813/*------------------------------------------------------------*/
2814
2815/* For all NEON DP ops, we use the normal scheme to handle conditional
2816   writes to registers -- pass in condT and hand that on to the
2817   put*Reg functions.  In ARM mode condT is always IRTemp_INVALID
2818   since NEON is unconditional for ARM.  In Thumb mode condT is
2819   derived from the ITSTATE shift register in the normal way. */
2820
2821static
2822UInt get_neon_d_regno(UInt theInstr)
2823{
2824   UInt x = ((theInstr >> 18) & 0x10) | ((theInstr >> 12) & 0xF);
2825   if (theInstr & 0x40) {
2826      if (x & 1) {
2827         x = x + 0x100;
2828      } else {
2829         x = x >> 1;
2830      }
2831   }
2832   return x;
2833}
2834
2835static
2836UInt get_neon_n_regno(UInt theInstr)
2837{
2838   UInt x = ((theInstr >> 3) & 0x10) | ((theInstr >> 16) & 0xF);
2839   if (theInstr & 0x40) {
2840      if (x & 1) {
2841         x = x + 0x100;
2842      } else {
2843         x = x >> 1;
2844      }
2845   }
2846   return x;
2847}
2848
2849static
2850UInt get_neon_m_regno(UInt theInstr)
2851{
2852   UInt x = ((theInstr >> 1) & 0x10) | (theInstr & 0xF);
2853   if (theInstr & 0x40) {
2854      if (x & 1) {
2855         x = x + 0x100;
2856      } else {
2857         x = x >> 1;
2858      }
2859   }
2860   return x;
2861}
2862
2863static
2864Bool dis_neon_vext ( UInt theInstr, IRTemp condT )
2865{
2866   UInt dreg = get_neon_d_regno(theInstr);
2867   UInt mreg = get_neon_m_regno(theInstr);
2868   UInt nreg = get_neon_n_regno(theInstr);
2869   UInt imm4 = (theInstr >> 8) & 0xf;
2870   UInt Q = (theInstr >> 6) & 1;
2871   HChar reg_t = Q ? 'q' : 'd';
2872
2873   if (Q) {
2874      putQReg(dreg, triop(Iop_ExtractV128, getQReg(nreg),
2875               getQReg(mreg), mkU8(imm4)), condT);
2876   } else {
2877      putDRegI64(dreg, triop(Iop_Extract64, getDRegI64(nreg),
2878                 getDRegI64(mreg), mkU8(imm4)), condT);
2879   }
2880   DIP("vext.8 %c%d, %c%d, %c%d, #%d\n", reg_t, dreg, reg_t, nreg,
2881                                         reg_t, mreg, imm4);
2882   return True;
2883}
2884
2885/* VTBL, VTBX */
2886static
2887Bool dis_neon_vtb ( UInt theInstr, IRTemp condT )
2888{
2889   UInt op = (theInstr >> 6) & 1;
2890   UInt dreg = get_neon_d_regno(theInstr & ~(1 << 6));
2891   UInt nreg = get_neon_n_regno(theInstr & ~(1 << 6));
2892   UInt mreg = get_neon_m_regno(theInstr & ~(1 << 6));
2893   UInt len = (theInstr >> 8) & 3;
2894   Int i;
2895   IROp cmp;
2896   ULong imm;
2897   IRTemp arg_l;
2898   IRTemp old_mask, new_mask, cur_mask;
2899   IRTemp old_res, new_res;
2900   IRTemp old_arg, new_arg;
2901
2902   if (dreg >= 0x100 || mreg >= 0x100 || nreg >= 0x100)
2903      return False;
2904   if (nreg + len > 31)
2905      return False;
2906
2907   cmp = Iop_CmpGT8Ux8;
2908
2909   old_mask = newTemp(Ity_I64);
2910   old_res = newTemp(Ity_I64);
2911   old_arg = newTemp(Ity_I64);
2912   assign(old_mask, mkU64(0));
2913   assign(old_res, mkU64(0));
2914   assign(old_arg, getDRegI64(mreg));
2915   imm = 8;
2916   imm = (imm <<  8) | imm;
2917   imm = (imm << 16) | imm;
2918   imm = (imm << 32) | imm;
2919
2920   for (i = 0; i <= len; i++) {
2921      arg_l = newTemp(Ity_I64);
2922      new_mask = newTemp(Ity_I64);
2923      cur_mask = newTemp(Ity_I64);
2924      new_res = newTemp(Ity_I64);
2925      new_arg = newTemp(Ity_I64);
2926      assign(arg_l, getDRegI64(nreg+i));
2927      assign(new_arg, binop(Iop_Sub8x8, mkexpr(old_arg), mkU64(imm)));
2928      assign(cur_mask, binop(cmp, mkU64(imm), mkexpr(old_arg)));
2929      assign(new_mask, binop(Iop_Or64, mkexpr(old_mask), mkexpr(cur_mask)));
2930      assign(new_res, binop(Iop_Or64,
2931                            mkexpr(old_res),
2932                            binop(Iop_And64,
2933                                  binop(Iop_Perm8x8,
2934                                        mkexpr(arg_l),
2935                                        binop(Iop_And64,
2936                                              mkexpr(old_arg),
2937                                              mkexpr(cur_mask))),
2938                                  mkexpr(cur_mask))));
2939
2940      old_arg = new_arg;
2941      old_mask = new_mask;
2942      old_res = new_res;
2943   }
2944   if (op) {
2945      new_res = newTemp(Ity_I64);
2946      assign(new_res, binop(Iop_Or64,
2947                            binop(Iop_And64,
2948                                  getDRegI64(dreg),
2949                                  unop(Iop_Not64, mkexpr(old_mask))),
2950                            mkexpr(old_res)));
2951      old_res = new_res;
2952   }
2953
2954   putDRegI64(dreg, mkexpr(old_res), condT);
2955   DIP("vtb%c.8 d%u, {", op ? 'x' : 'l', dreg);
2956   if (len > 0) {
2957      DIP("d%u-d%u", nreg, nreg + len);
2958   } else {
2959      DIP("d%u", nreg);
2960   }
2961   DIP("}, d%u\n", mreg);
2962   return True;
2963}
2964
2965/* VDUP (scalar)  */
2966static
2967Bool dis_neon_vdup ( UInt theInstr, IRTemp condT )
2968{
2969   UInt Q = (theInstr >> 6) & 1;
2970   UInt dreg = ((theInstr >> 18) & 0x10) | ((theInstr >> 12) & 0xF);
2971   UInt mreg = ((theInstr >> 1) & 0x10) | (theInstr & 0xF);
2972   UInt imm4 = (theInstr >> 16) & 0xF;
2973   UInt index;
2974   UInt size;
2975   IRTemp arg_m;
2976   IRTemp res;
2977   IROp op, op2;
2978
2979   if ((imm4 == 0) || (imm4 == 8))
2980      return False;
2981   if ((Q == 1) && ((dreg & 1) == 1))
2982      return False;
2983   if (Q)
2984      dreg >>= 1;
2985   arg_m = newTemp(Ity_I64);
2986   assign(arg_m, getDRegI64(mreg));
2987   if (Q)
2988      res = newTemp(Ity_V128);
2989   else
2990      res = newTemp(Ity_I64);
2991   if ((imm4 & 1) == 1) {
2992      op = Q ? Iop_Dup8x16 : Iop_Dup8x8;
2993      op2 = Iop_GetElem8x8;
2994      index = imm4 >> 1;
2995      size = 8;
2996   } else if ((imm4 & 3) == 2) {
2997      op = Q ? Iop_Dup16x8 : Iop_Dup16x4;
2998      op2 = Iop_GetElem16x4;
2999      index = imm4 >> 2;
3000      size = 16;
3001   } else if ((imm4 & 7) == 4) {
3002      op = Q ? Iop_Dup32x4 : Iop_Dup32x2;
3003      op2 = Iop_GetElem32x2;
3004      index = imm4 >> 3;
3005      size = 32;
3006   } else {
3007      return False; // can this ever happen?
3008   }
3009   assign(res, unop(op, binop(op2, mkexpr(arg_m), mkU8(index))));
3010   if (Q) {
3011      putQReg(dreg, mkexpr(res), condT);
3012   } else {
3013      putDRegI64(dreg, mkexpr(res), condT);
3014   }
3015   DIP("vdup.%d %c%d, d%d[%d]\n", size, Q ? 'q' : 'd', dreg, mreg, index);
3016   return True;
3017}
3018
3019/* A7.4.1 Three registers of the same length */
3020static
3021Bool dis_neon_data_3same ( UInt theInstr, IRTemp condT )
3022{
3023   UInt Q = (theInstr >> 6) & 1;
3024   UInt dreg = get_neon_d_regno(theInstr);
3025   UInt nreg = get_neon_n_regno(theInstr);
3026   UInt mreg = get_neon_m_regno(theInstr);
3027   UInt A = (theInstr >> 8) & 0xF;
3028   UInt B = (theInstr >> 4) & 1;
3029   UInt C = (theInstr >> 20) & 0x3;
3030   UInt U = (theInstr >> 24) & 1;
3031   UInt size = C;
3032
3033   IRTemp arg_n;
3034   IRTemp arg_m;
3035   IRTemp res;
3036
3037   if (Q) {
3038      arg_n = newTemp(Ity_V128);
3039      arg_m = newTemp(Ity_V128);
3040      res = newTemp(Ity_V128);
3041      assign(arg_n, getQReg(nreg));
3042      assign(arg_m, getQReg(mreg));
3043   } else {
3044      arg_n = newTemp(Ity_I64);
3045      arg_m = newTemp(Ity_I64);
3046      res = newTemp(Ity_I64);
3047      assign(arg_n, getDRegI64(nreg));
3048      assign(arg_m, getDRegI64(mreg));
3049   }
3050
3051   switch(A) {
3052      case 0:
3053         if (B == 0) {
3054            /* VHADD */
3055            ULong imm = 0;
3056            IRExpr *imm_val;
3057            IROp addOp;
3058            IROp andOp;
3059            IROp shOp;
3060            char regType = Q ? 'q' : 'd';
3061
3062            if (size == 3)
3063               return False;
3064            switch(size) {
3065               case 0: imm = 0x101010101010101LL; break;
3066               case 1: imm = 0x1000100010001LL; break;
3067               case 2: imm = 0x100000001LL; break;
3068               default: vassert(0);
3069            }
3070            if (Q) {
3071               imm_val = binop(Iop_64HLtoV128, mkU64(imm), mkU64(imm));
3072               andOp = Iop_AndV128;
3073            } else {
3074               imm_val = mkU64(imm);
3075               andOp = Iop_And64;
3076            }
3077            if (U) {
3078               switch(size) {
3079                  case 0:
3080                     addOp = Q ? Iop_Add8x16 : Iop_Add8x8;
3081                     shOp = Q ? Iop_ShrN8x16 : Iop_ShrN8x8;
3082                     break;
3083                  case 1:
3084                     addOp = Q ? Iop_Add16x8 : Iop_Add16x4;
3085                     shOp = Q ? Iop_ShrN16x8 : Iop_ShrN16x4;
3086                     break;
3087                  case 2:
3088                     addOp = Q ? Iop_Add32x4 : Iop_Add32x2;
3089                     shOp = Q ? Iop_ShrN32x4 : Iop_ShrN32x2;
3090                     break;
3091                  default:
3092                     vassert(0);
3093               }
3094            } else {
3095               switch(size) {
3096                  case 0:
3097                     addOp = Q ? Iop_Add8x16 : Iop_Add8x8;
3098                     shOp = Q ? Iop_SarN8x16 : Iop_SarN8x8;
3099                     break;
3100                  case 1:
3101                     addOp = Q ? Iop_Add16x8 : Iop_Add16x4;
3102                     shOp = Q ? Iop_SarN16x8 : Iop_SarN16x4;
3103                     break;
3104                  case 2:
3105                     addOp = Q ? Iop_Add32x4 : Iop_Add32x2;
3106                     shOp = Q ? Iop_SarN32x4 : Iop_SarN32x2;
3107                     break;
3108                  default:
3109                     vassert(0);
3110               }
3111            }
3112            assign(res,
3113                   binop(addOp,
3114                         binop(addOp,
3115                               binop(shOp, mkexpr(arg_m), mkU8(1)),
3116                               binop(shOp, mkexpr(arg_n), mkU8(1))),
3117                         binop(shOp,
3118                               binop(addOp,
3119                                     binop(andOp, mkexpr(arg_m), imm_val),
3120                                     binop(andOp, mkexpr(arg_n), imm_val)),
3121                               mkU8(1))));
3122            DIP("vhadd.%c%d %c%d, %c%d, %c%d\n",
3123                U ? 'u' : 's', 8 << size, regType,
3124                dreg, regType, nreg, regType, mreg);
3125         } else {
3126            /* VQADD */
3127            IROp op, op2;
3128            IRTemp tmp;
3129            char reg_t = Q ? 'q' : 'd';
3130            if (Q) {
3131               switch (size) {
3132                  case 0:
3133                     op = U ? Iop_QAdd8Ux16 : Iop_QAdd8Sx16;
3134                     op2 = Iop_Add8x16;
3135                     break;
3136                  case 1:
3137                     op = U ? Iop_QAdd16Ux8 : Iop_QAdd16Sx8;
3138                     op2 = Iop_Add16x8;
3139                     break;
3140                  case 2:
3141                     op = U ? Iop_QAdd32Ux4 : Iop_QAdd32Sx4;
3142                     op2 = Iop_Add32x4;
3143                     break;
3144                  case 3:
3145                     op = U ? Iop_QAdd64Ux2 : Iop_QAdd64Sx2;
3146                     op2 = Iop_Add64x2;
3147                     break;
3148                  default:
3149                     vassert(0);
3150               }
3151            } else {
3152               switch (size) {
3153                  case 0:
3154                     op = U ? Iop_QAdd8Ux8 : Iop_QAdd8Sx8;
3155                     op2 = Iop_Add8x8;
3156                     break;
3157                  case 1:
3158                     op = U ? Iop_QAdd16Ux4 : Iop_QAdd16Sx4;
3159                     op2 = Iop_Add16x4;
3160                     break;
3161                  case 2:
3162                     op = U ? Iop_QAdd32Ux2 : Iop_QAdd32Sx2;
3163                     op2 = Iop_Add32x2;
3164                     break;
3165                  case 3:
3166                     op = U ? Iop_QAdd64Ux1 : Iop_QAdd64Sx1;
3167                     op2 = Iop_Add64;
3168                     break;
3169                  default:
3170                     vassert(0);
3171               }
3172            }
3173            if (Q) {
3174               tmp = newTemp(Ity_V128);
3175            } else {
3176               tmp = newTemp(Ity_I64);
3177            }
3178            assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m)));
3179#ifndef DISABLE_QC_FLAG
3180            assign(tmp, binop(op2, mkexpr(arg_n), mkexpr(arg_m)));
3181            setFlag_QC(mkexpr(res), mkexpr(tmp), Q, condT);
3182#endif
3183            DIP("vqadd.%c%d %c%d, %c%d, %c%d\n",
3184                U ? 'u' : 's',
3185                8 << size, reg_t, dreg, reg_t, nreg, reg_t, mreg);
3186         }
3187         break;
3188      case 1:
3189         if (B == 0) {
3190            /* VRHADD */
3191            /* VRHADD C, A, B ::=
3192                 C = (A >> 1) + (B >> 1) + (((A & 1) + (B & 1) + 1) >> 1) */
3193            IROp shift_op, add_op;
3194            IRTemp cc;
3195            ULong one = 1;
3196            HChar reg_t = Q ? 'q' : 'd';
3197            switch (size) {
3198               case 0: one = (one <<  8) | one; /* fall through */
3199               case 1: one = (one << 16) | one; /* fall through */
3200               case 2: one = (one << 32) | one; break;
3201               case 3: return False;
3202               default: vassert(0);
3203            }
3204            if (Q) {
3205               switch (size) {
3206                  case 0:
3207                     shift_op = U ? Iop_ShrN8x16 : Iop_SarN8x16;
3208                     add_op = Iop_Add8x16;
3209                     break;
3210                  case 1:
3211                     shift_op = U ? Iop_ShrN16x8 : Iop_SarN16x8;
3212                     add_op = Iop_Add16x8;
3213                     break;
3214                  case 2:
3215                     shift_op = U ? Iop_ShrN32x4 : Iop_SarN32x4;
3216                     add_op = Iop_Add32x4;
3217                     break;
3218                  case 3:
3219                     return False;
3220                  default:
3221                     vassert(0);
3222               }
3223            } else {
3224               switch (size) {
3225                  case 0:
3226                     shift_op = U ? Iop_ShrN8x8 : Iop_SarN8x8;
3227                     add_op = Iop_Add8x8;
3228                     break;
3229                  case 1:
3230                     shift_op = U ? Iop_ShrN16x4 : Iop_SarN16x4;
3231                     add_op = Iop_Add16x4;
3232                     break;
3233                  case 2:
3234                     shift_op = U ? Iop_ShrN32x2 : Iop_SarN32x2;
3235                     add_op = Iop_Add32x2;
3236                     break;
3237                  case 3:
3238                     return False;
3239                  default:
3240                     vassert(0);
3241               }
3242            }
3243            if (Q) {
3244               cc = newTemp(Ity_V128);
3245               assign(cc, binop(shift_op,
3246                                binop(add_op,
3247                                      binop(add_op,
3248                                            binop(Iop_AndV128,
3249                                                  mkexpr(arg_n),
3250                                                  binop(Iop_64HLtoV128,
3251                                                        mkU64(one),
3252                                                        mkU64(one))),
3253                                            binop(Iop_AndV128,
3254                                                  mkexpr(arg_m),
3255                                                  binop(Iop_64HLtoV128,
3256                                                        mkU64(one),
3257                                                        mkU64(one)))),
3258                                      binop(Iop_64HLtoV128,
3259                                            mkU64(one),
3260                                            mkU64(one))),
3261                                mkU8(1)));
3262               assign(res, binop(add_op,
3263                                 binop(add_op,
3264                                       binop(shift_op,
3265                                             mkexpr(arg_n),
3266                                             mkU8(1)),
3267                                       binop(shift_op,
3268                                             mkexpr(arg_m),
3269                                             mkU8(1))),
3270                                 mkexpr(cc)));
3271            } else {
3272               cc = newTemp(Ity_I64);
3273               assign(cc, binop(shift_op,
3274                                binop(add_op,
3275                                      binop(add_op,
3276                                            binop(Iop_And64,
3277                                                  mkexpr(arg_n),
3278                                                  mkU64(one)),
3279                                            binop(Iop_And64,
3280                                                  mkexpr(arg_m),
3281                                                  mkU64(one))),
3282                                      mkU64(one)),
3283                                mkU8(1)));
3284               assign(res, binop(add_op,
3285                                 binop(add_op,
3286                                       binop(shift_op,
3287                                             mkexpr(arg_n),
3288                                             mkU8(1)),
3289                                       binop(shift_op,
3290                                             mkexpr(arg_m),
3291                                             mkU8(1))),
3292                                 mkexpr(cc)));
3293            }
3294            DIP("vrhadd.%c%d %c%d, %c%d, %c%d\n",
3295                U ? 'u' : 's',
3296                8 << size, reg_t, dreg, reg_t, nreg, reg_t, mreg);
3297         } else {
3298            if (U == 0)  {
3299               switch(C) {
3300                  case 0: {
3301                     /* VAND  */
3302                     HChar reg_t = Q ? 'q' : 'd';
3303                     if (Q) {
3304                        assign(res, binop(Iop_AndV128, mkexpr(arg_n),
3305                                                       mkexpr(arg_m)));
3306                     } else {
3307                        assign(res, binop(Iop_And64, mkexpr(arg_n),
3308                                                     mkexpr(arg_m)));
3309                     }
3310                     DIP("vand %c%d, %c%d, %c%d\n",
3311                         reg_t, dreg, reg_t, nreg, reg_t, mreg);
3312                     break;
3313                  }
3314                  case 1: {
3315                     /* VBIC  */
3316                     HChar reg_t = Q ? 'q' : 'd';
3317                     if (Q) {
3318                        assign(res, binop(Iop_AndV128,mkexpr(arg_n),
3319                               unop(Iop_NotV128, mkexpr(arg_m))));
3320                     } else {
3321                        assign(res, binop(Iop_And64, mkexpr(arg_n),
3322                               unop(Iop_Not64, mkexpr(arg_m))));
3323                     }
3324                     DIP("vbic %c%d, %c%d, %c%d\n",
3325                         reg_t, dreg, reg_t, nreg, reg_t, mreg);
3326                     break;
3327                  }
3328                  case 2:
3329                     if ( nreg != mreg) {
3330                        /* VORR  */
3331                        HChar reg_t = Q ? 'q' : 'd';
3332                        if (Q) {
3333                           assign(res, binop(Iop_OrV128, mkexpr(arg_n),
3334                                                         mkexpr(arg_m)));
3335                        } else {
3336                           assign(res, binop(Iop_Or64, mkexpr(arg_n),
3337                                                       mkexpr(arg_m)));
3338                        }
3339                        DIP("vorr %c%d, %c%d, %c%d\n",
3340                            reg_t, dreg, reg_t, nreg, reg_t, mreg);
3341                     } else {
3342                        /* VMOV  */
3343                        HChar reg_t = Q ? 'q' : 'd';
3344                        assign(res, mkexpr(arg_m));
3345                        DIP("vmov %c%d, %c%d\n", reg_t, dreg, reg_t, mreg);
3346                     }
3347                     break;
3348                  case 3:{
3349                     /* VORN  */
3350                     HChar reg_t = Q ? 'q' : 'd';
3351                     if (Q) {
3352                        assign(res, binop(Iop_OrV128,mkexpr(arg_n),
3353                               unop(Iop_NotV128, mkexpr(arg_m))));
3354                     } else {
3355                        assign(res, binop(Iop_Or64, mkexpr(arg_n),
3356                               unop(Iop_Not64, mkexpr(arg_m))));
3357                     }
3358                     DIP("vorn %c%d, %c%d, %c%d\n",
3359                         reg_t, dreg, reg_t, nreg, reg_t, mreg);
3360                     break;
3361                  }
3362               }
3363            } else {
3364               switch(C) {
3365                  case 0:
3366                     /* VEOR (XOR)  */
3367                     if (Q) {
3368                        assign(res, binop(Iop_XorV128, mkexpr(arg_n),
3369                                                       mkexpr(arg_m)));
3370                     } else {
3371                        assign(res, binop(Iop_Xor64, mkexpr(arg_n),
3372                                                     mkexpr(arg_m)));
3373                     }
3374                     DIP("veor %c%u, %c%u, %c%u\n", Q ? 'q' : 'd', dreg,
3375                           Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg);
3376                     break;
3377                  case 1:
3378                     /* VBSL  */
3379                     if (Q) {
3380                        IRTemp reg_d = newTemp(Ity_V128);
3381                        assign(reg_d, getQReg(dreg));
3382                        assign(res,
3383                               binop(Iop_OrV128,
3384                                     binop(Iop_AndV128, mkexpr(arg_n),
3385                                                        mkexpr(reg_d)),
3386                                     binop(Iop_AndV128,
3387                                           mkexpr(arg_m),
3388                                           unop(Iop_NotV128,
3389                                                 mkexpr(reg_d)) ) ) );
3390                     } else {
3391                        IRTemp reg_d = newTemp(Ity_I64);
3392                        assign(reg_d, getDRegI64(dreg));
3393                        assign(res,
3394                               binop(Iop_Or64,
3395                                     binop(Iop_And64, mkexpr(arg_n),
3396                                                      mkexpr(reg_d)),
3397                                     binop(Iop_And64,
3398                                           mkexpr(arg_m),
3399                                           unop(Iop_Not64, mkexpr(reg_d)))));
3400                     }
3401                     DIP("vbsl %c%u, %c%u, %c%u\n",
3402                         Q ? 'q' : 'd', dreg,
3403                         Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg);
3404                     break;
3405                  case 2:
3406                     /* VBIT  */
3407                     if (Q) {
3408                        IRTemp reg_d = newTemp(Ity_V128);
3409                        assign(reg_d, getQReg(dreg));
3410                        assign(res,
3411                               binop(Iop_OrV128,
3412                                     binop(Iop_AndV128, mkexpr(arg_n),
3413                                                        mkexpr(arg_m)),
3414                                     binop(Iop_AndV128,
3415                                           mkexpr(reg_d),
3416                                           unop(Iop_NotV128, mkexpr(arg_m)))));
3417                     } else {
3418                        IRTemp reg_d = newTemp(Ity_I64);
3419                        assign(reg_d, getDRegI64(dreg));
3420                        assign(res,
3421                               binop(Iop_Or64,
3422                                     binop(Iop_And64, mkexpr(arg_n),
3423                                                      mkexpr(arg_m)),
3424                                     binop(Iop_And64,
3425                                           mkexpr(reg_d),
3426                                           unop(Iop_Not64, mkexpr(arg_m)))));
3427                     }
3428                     DIP("vbit %c%u, %c%u, %c%u\n",
3429                         Q ? 'q' : 'd', dreg,
3430                         Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg);
3431                     break;
3432                  case 3:
3433                     /* VBIF  */
3434                     if (Q) {
3435                        IRTemp reg_d = newTemp(Ity_V128);
3436                        assign(reg_d, getQReg(dreg));
3437                        assign(res,
3438                               binop(Iop_OrV128,
3439                                     binop(Iop_AndV128, mkexpr(reg_d),
3440                                                        mkexpr(arg_m)),
3441                                     binop(Iop_AndV128,
3442                                           mkexpr(arg_n),
3443                                           unop(Iop_NotV128, mkexpr(arg_m)))));
3444                     } else {
3445                        IRTemp reg_d = newTemp(Ity_I64);
3446                        assign(reg_d, getDRegI64(dreg));
3447                        assign(res,
3448                               binop(Iop_Or64,
3449                                     binop(Iop_And64, mkexpr(reg_d),
3450                                                      mkexpr(arg_m)),
3451                                     binop(Iop_And64,
3452                                           mkexpr(arg_n),
3453                                           unop(Iop_Not64, mkexpr(arg_m)))));
3454                     }
3455                     DIP("vbif %c%u, %c%u, %c%u\n",
3456                         Q ? 'q' : 'd', dreg,
3457                         Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg);
3458                     break;
3459               }
3460            }
3461         }
3462         break;
3463      case 2:
3464         if (B == 0) {
3465            /* VHSUB */
3466            /* (A >> 1) - (B >> 1) - (NOT (A) & B & 1)   */
3467            ULong imm = 0;
3468            IRExpr *imm_val;
3469            IROp subOp;
3470            IROp notOp;
3471            IROp andOp;
3472            IROp shOp;
3473            if (size == 3)
3474               return False;
3475            switch(size) {
3476               case 0: imm = 0x101010101010101LL; break;
3477               case 1: imm = 0x1000100010001LL; break;
3478               case 2: imm = 0x100000001LL; break;
3479               default: vassert(0);
3480            }
3481            if (Q) {
3482               imm_val = binop(Iop_64HLtoV128, mkU64(imm), mkU64(imm));
3483               andOp = Iop_AndV128;
3484               notOp = Iop_NotV128;
3485            } else {
3486               imm_val = mkU64(imm);
3487               andOp = Iop_And64;
3488               notOp = Iop_Not64;
3489            }
3490            if (U) {
3491               switch(size) {
3492                  case 0:
3493                     subOp = Q ? Iop_Sub8x16 : Iop_Sub8x8;
3494                     shOp = Q ? Iop_ShrN8x16 : Iop_ShrN8x8;
3495                     break;
3496                  case 1:
3497                     subOp = Q ? Iop_Sub16x8 : Iop_Sub16x4;
3498                     shOp = Q ? Iop_ShrN16x8 : Iop_ShrN16x4;
3499                     break;
3500                  case 2:
3501                     subOp = Q ? Iop_Sub32x4 : Iop_Sub32x2;
3502                     shOp = Q ? Iop_ShrN32x4 : Iop_ShrN32x2;
3503                     break;
3504                  default:
3505                     vassert(0);
3506               }
3507            } else {
3508               switch(size) {
3509                  case 0:
3510                     subOp = Q ? Iop_Sub8x16 : Iop_Sub8x8;
3511                     shOp = Q ? Iop_SarN8x16 : Iop_SarN8x8;
3512                     break;
3513                  case 1:
3514                     subOp = Q ? Iop_Sub16x8 : Iop_Sub16x4;
3515                     shOp = Q ? Iop_SarN16x8 : Iop_SarN16x4;
3516                     break;
3517                  case 2:
3518                     subOp = Q ? Iop_Sub32x4 : Iop_Sub32x2;
3519                     shOp = Q ? Iop_SarN32x4 : Iop_SarN32x2;
3520                     break;
3521                  default:
3522                     vassert(0);
3523               }
3524            }
3525            assign(res,
3526                   binop(subOp,
3527                         binop(subOp,
3528                               binop(shOp, mkexpr(arg_n), mkU8(1)),
3529                               binop(shOp, mkexpr(arg_m), mkU8(1))),
3530                         binop(andOp,
3531                               binop(andOp,
3532                                     unop(notOp, mkexpr(arg_n)),
3533                                     mkexpr(arg_m)),
3534                               imm_val)));
3535            DIP("vhsub.%c%u %c%u, %c%u, %c%u\n",
3536                U ? 'u' : 's', 8 << size,
3537                Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', nreg, Q ? 'q' : 'd',
3538                mreg);
3539         } else {
3540            /* VQSUB */
3541            IROp op, op2;
3542            IRTemp tmp;
3543            if (Q) {
3544               switch (size) {
3545                  case 0:
3546                     op = U ? Iop_QSub8Ux16 : Iop_QSub8Sx16;
3547                     op2 = Iop_Sub8x16;
3548                     break;
3549                  case 1:
3550                     op = U ? Iop_QSub16Ux8 : Iop_QSub16Sx8;
3551                     op2 = Iop_Sub16x8;
3552                     break;
3553                  case 2:
3554                     op = U ? Iop_QSub32Ux4 : Iop_QSub32Sx4;
3555                     op2 = Iop_Sub32x4;
3556                     break;
3557                  case 3:
3558                     op = U ? Iop_QSub64Ux2 : Iop_QSub64Sx2;
3559                     op2 = Iop_Sub64x2;
3560                     break;
3561                  default:
3562                     vassert(0);
3563               }
3564            } else {
3565               switch (size) {
3566                  case 0:
3567                     op = U ? Iop_QSub8Ux8 : Iop_QSub8Sx8;
3568                     op2 = Iop_Sub8x8;
3569                     break;
3570                  case 1:
3571                     op = U ? Iop_QSub16Ux4 : Iop_QSub16Sx4;
3572                     op2 = Iop_Sub16x4;
3573                     break;
3574                  case 2:
3575                     op = U ? Iop_QSub32Ux2 : Iop_QSub32Sx2;
3576                     op2 = Iop_Sub32x2;
3577                     break;
3578                  case 3:
3579                     op = U ? Iop_QSub64Ux1 : Iop_QSub64Sx1;
3580                     op2 = Iop_Sub64;
3581                     break;
3582                  default:
3583                     vassert(0);
3584               }
3585            }
3586            if (Q)
3587               tmp = newTemp(Ity_V128);
3588            else
3589               tmp = newTemp(Ity_I64);
3590            assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m)));
3591#ifndef DISABLE_QC_FLAG
3592            assign(tmp, binop(op2, mkexpr(arg_n), mkexpr(arg_m)));
3593            setFlag_QC(mkexpr(res), mkexpr(tmp), Q, condT);
3594#endif
3595            DIP("vqsub.%c%u %c%u, %c%u, %c%u\n",
3596                U ? 'u' : 's', 8 << size,
3597                Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', nreg, Q ? 'q' : 'd',
3598                mreg);
3599         }
3600         break;
3601      case 3: {
3602            IROp op;
3603            if (Q) {
3604               switch (size) {
3605                  case 0: op = U ? Iop_CmpGT8Ux16 : Iop_CmpGT8Sx16; break;
3606                  case 1: op = U ? Iop_CmpGT16Ux8 : Iop_CmpGT16Sx8; break;
3607                  case 2: op = U ? Iop_CmpGT32Ux4 : Iop_CmpGT32Sx4; break;
3608                  case 3: return False;
3609                  default: vassert(0);
3610               }
3611            } else {
3612               switch (size) {
3613                  case 0: op = U ? Iop_CmpGT8Ux8 : Iop_CmpGT8Sx8; break;
3614                  case 1: op = U ? Iop_CmpGT16Ux4 : Iop_CmpGT16Sx4; break;
3615                  case 2: op = U ? Iop_CmpGT32Ux2: Iop_CmpGT32Sx2; break;
3616                  case 3: return False;
3617                  default: vassert(0);
3618               }
3619            }
3620            if (B == 0) {
3621               /* VCGT  */
3622               assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m)));
3623               DIP("vcgt.%c%u %c%u, %c%u, %c%u\n",
3624                   U ? 'u' : 's', 8 << size,
3625                   Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', nreg, Q ? 'q' : 'd',
3626                   mreg);
3627            } else {
3628               /* VCGE  */
3629               /* VCGE res, argn, argm
3630                    is equal to
3631                  VCGT tmp, argm, argn
3632                  VNOT res, tmp */
3633               assign(res,
3634                      unop(Q ? Iop_NotV128 : Iop_Not64,
3635                           binop(op, mkexpr(arg_m), mkexpr(arg_n))));
3636               DIP("vcge.%c%u %c%u, %c%u, %c%u\n",
3637                   U ? 'u' : 's', 8 << size,
3638                   Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', nreg, Q ? 'q' : 'd',
3639                   mreg);
3640            }
3641         }
3642         break;
3643      case 4:
3644         if (B == 0) {
3645            /* VSHL */
3646            IROp op, sub_op;
3647            IRTemp tmp;
3648            if (U) {
3649               switch (size) {
3650                  case 0: op = Q ? Iop_Shl8x16 : Iop_Shl8x8; break;
3651                  case 1: op = Q ? Iop_Shl16x8 : Iop_Shl16x4; break;
3652                  case 2: op = Q ? Iop_Shl32x4 : Iop_Shl32x2; break;
3653                  case 3: op = Q ? Iop_Shl64x2 : Iop_Shl64; break;
3654                  default: vassert(0);
3655               }
3656            } else {
3657               tmp = newTemp(Q ? Ity_V128 : Ity_I64);
3658               switch (size) {
3659                  case 0:
3660                     op = Q ? Iop_Sar8x16 : Iop_Sar8x8;
3661                     sub_op = Q ? Iop_Sub8x16 : Iop_Sub8x8;
3662                     break;
3663                  case 1:
3664                     op = Q ? Iop_Sar16x8 : Iop_Sar16x4;
3665                     sub_op = Q ? Iop_Sub16x8 : Iop_Sub16x4;
3666                     break;
3667                  case 2:
3668                     op = Q ? Iop_Sar32x4 : Iop_Sar32x2;
3669                     sub_op = Q ? Iop_Sub32x4 : Iop_Sub32x2;
3670                     break;
3671                  case 3:
3672                     op = Q ? Iop_Sar64x2 : Iop_Sar64;
3673                     sub_op = Q ? Iop_Sub64x2 : Iop_Sub64;
3674                     break;
3675                  default:
3676                     vassert(0);
3677               }
3678            }
3679            if (U) {
3680               if (!Q && (size == 3))
3681                  assign(res, binop(op, mkexpr(arg_m),
3682                                        unop(Iop_64to8, mkexpr(arg_n))));
3683               else
3684                  assign(res, binop(op, mkexpr(arg_m), mkexpr(arg_n)));
3685            } else {
3686               if (Q)
3687                  assign(tmp, binop(sub_op,
3688                                    binop(Iop_64HLtoV128, mkU64(0), mkU64(0)),
3689                                    mkexpr(arg_n)));
3690               else
3691                  assign(tmp, binop(sub_op, mkU64(0), mkexpr(arg_n)));
3692               if (!Q && (size == 3))
3693                  assign(res, binop(op, mkexpr(arg_m),
3694                                        unop(Iop_64to8, mkexpr(tmp))));
3695               else
3696                  assign(res, binop(op, mkexpr(arg_m), mkexpr(tmp)));
3697            }
3698            DIP("vshl.%c%u %c%u, %c%u, %c%u\n",
3699                U ? 'u' : 's', 8 << size,
3700                Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg, Q ? 'q' : 'd',
3701                nreg);
3702         } else {
3703            /* VQSHL */
3704            IROp op, op_rev, op_shrn, op_shln, cmp_neq, cmp_gt;
3705            IRTemp tmp, shval, mask, old_shval;
3706            UInt i;
3707            ULong esize;
3708            cmp_neq = Q ? Iop_CmpNEZ8x16 : Iop_CmpNEZ8x8;
3709            cmp_gt = Q ? Iop_CmpGT8Sx16 : Iop_CmpGT8Sx8;
3710            if (U) {
3711               switch (size) {
3712                  case 0:
3713                     op = Q ? Iop_QShl8x16 : Iop_QShl8x8;
3714                     op_rev = Q ? Iop_Shr8x16 : Iop_Shr8x8;
3715                     op_shrn = Q ? Iop_ShrN8x16 : Iop_ShrN8x8;
3716                     op_shln = Q ? Iop_ShlN8x16 : Iop_ShlN8x8;
3717                     break;
3718                  case 1:
3719                     op = Q ? Iop_QShl16x8 : Iop_QShl16x4;
3720                     op_rev = Q ? Iop_Shr16x8 : Iop_Shr16x4;
3721                     op_shrn = Q ? Iop_ShrN16x8 : Iop_ShrN16x4;
3722                     op_shln = Q ? Iop_ShlN16x8 : Iop_ShlN16x4;
3723                     break;
3724                  case 2:
3725                     op = Q ? Iop_QShl32x4 : Iop_QShl32x2;
3726                     op_rev = Q ? Iop_Shr32x4 : Iop_Shr32x2;
3727                     op_shrn = Q ? Iop_ShrN32x4 : Iop_ShrN32x2;
3728                     op_shln = Q ? Iop_ShlN32x4 : Iop_ShlN32x2;
3729                     break;
3730                  case 3:
3731                     op = Q ? Iop_QShl64x2 : Iop_QShl64x1;
3732                     op_rev = Q ? Iop_Shr64x2 : Iop_Shr64;
3733                     op_shrn = Q ? Iop_ShrN64x2 : Iop_Shr64;
3734                     op_shln = Q ? Iop_ShlN64x2 : Iop_Shl64;
3735                     break;
3736                  default:
3737                     vassert(0);
3738               }
3739            } else {
3740               switch (size) {
3741                  case 0:
3742                     op = Q ? Iop_QSal8x16 : Iop_QSal8x8;
3743                     op_rev = Q ? Iop_Sar8x16 : Iop_Sar8x8;
3744                     op_shrn = Q ? Iop_ShrN8x16 : Iop_ShrN8x8;
3745                     op_shln = Q ? Iop_ShlN8x16 : Iop_ShlN8x8;
3746                     break;
3747                  case 1:
3748                     op = Q ? Iop_QSal16x8 : Iop_QSal16x4;
3749                     op_rev = Q ? Iop_Sar16x8 : Iop_Sar16x4;
3750                     op_shrn = Q ? Iop_ShrN16x8 : Iop_ShrN16x4;
3751                     op_shln = Q ? Iop_ShlN16x8 : Iop_ShlN16x4;
3752                     break;
3753                  case 2:
3754                     op = Q ? Iop_QSal32x4 : Iop_QSal32x2;
3755                     op_rev = Q ? Iop_Sar32x4 : Iop_Sar32x2;
3756                     op_shrn = Q ? Iop_ShrN32x4 : Iop_ShrN32x2;
3757                     op_shln = Q ? Iop_ShlN32x4 : Iop_ShlN32x2;
3758                     break;
3759                  case 3:
3760                     op = Q ? Iop_QSal64x2 : Iop_QSal64x1;
3761                     op_rev = Q ? Iop_Sar64x2 : Iop_Sar64;
3762                     op_shrn = Q ? Iop_ShrN64x2 : Iop_Shr64;
3763                     op_shln = Q ? Iop_ShlN64x2 : Iop_Shl64;
3764                     break;
3765                  default:
3766                     vassert(0);
3767               }
3768            }
3769            if (Q) {
3770               tmp = newTemp(Ity_V128);
3771               shval = newTemp(Ity_V128);
3772               mask = newTemp(Ity_V128);
3773            } else {
3774               tmp = newTemp(Ity_I64);
3775               shval = newTemp(Ity_I64);
3776               mask = newTemp(Ity_I64);
3777            }
3778            assign(res, binop(op, mkexpr(arg_m), mkexpr(arg_n)));
3779#ifndef DISABLE_QC_FLAG
3780            /* Only least significant byte from second argument is used.
3781               Copy this byte to the whole vector element. */
3782            assign(shval, binop(op_shrn,
3783                                binop(op_shln,
3784                                       mkexpr(arg_n),
3785                                       mkU8((8 << size) - 8)),
3786                                mkU8((8 << size) - 8)));
3787            for(i = 0; i < size; i++) {
3788               old_shval = shval;
3789               shval = newTemp(Q ? Ity_V128 : Ity_I64);
3790               assign(shval, binop(Q ? Iop_OrV128 : Iop_Or64,
3791                                   mkexpr(old_shval),
3792                                   binop(op_shln,
3793                                         mkexpr(old_shval),
3794                                         mkU8(8 << i))));
3795            }
3796            /* If shift is greater or equal to the element size and
3797               element is non-zero, then QC flag should be set. */
3798            esize = (8 << size) - 1;
3799            esize = (esize <<  8) | esize;
3800            esize = (esize << 16) | esize;
3801            esize = (esize << 32) | esize;
3802            setFlag_QC(binop(Q ? Iop_AndV128 : Iop_And64,
3803                             binop(cmp_gt, mkexpr(shval),
3804                                           Q ? mkU128(esize) : mkU64(esize)),
3805                             unop(cmp_neq, mkexpr(arg_m))),
3806                       Q ? mkU128(0) : mkU64(0),
3807                       Q, condT);
3808            /* Othervise QC flag should be set if shift value is positive and
3809               result beign rightshifted the same value is not equal to left
3810               argument. */
3811            assign(mask, binop(cmp_gt, mkexpr(shval),
3812                                       Q ? mkU128(0) : mkU64(0)));
3813            if (!Q && size == 3)
3814               assign(tmp, binop(op_rev, mkexpr(res),
3815                                         unop(Iop_64to8, mkexpr(arg_n))));
3816            else
3817               assign(tmp, binop(op_rev, mkexpr(res), mkexpr(arg_n)));
3818            setFlag_QC(binop(Q ? Iop_AndV128 : Iop_And64,
3819                             mkexpr(tmp), mkexpr(mask)),
3820                       binop(Q ? Iop_AndV128 : Iop_And64,
3821                             mkexpr(arg_m), mkexpr(mask)),
3822                       Q, condT);
3823#endif
3824            DIP("vqshl.%c%u %c%u, %c%u, %c%u\n",
3825                U ? 'u' : 's', 8 << size,
3826                Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg, Q ? 'q' : 'd',
3827                nreg);
3828         }
3829         break;
3830      case 5:
3831         if (B == 0) {
3832            /* VRSHL */
3833            IROp op, op_shrn, op_shln, cmp_gt, op_add;
3834            IRTemp shval, old_shval, imm_val, round;
3835            UInt i;
3836            ULong imm;
3837            cmp_gt = Q ? Iop_CmpGT8Sx16 : Iop_CmpGT8Sx8;
3838            imm = 1L;
3839            switch (size) {
3840               case 0: imm = (imm <<  8) | imm; /* fall through */
3841               case 1: imm = (imm << 16) | imm; /* fall through */
3842               case 2: imm = (imm << 32) | imm; /* fall through */
3843               case 3: break;
3844               default: vassert(0);
3845            }
3846            imm_val = newTemp(Q ? Ity_V128 : Ity_I64);
3847            round = newTemp(Q ? Ity_V128 : Ity_I64);
3848            assign(imm_val, Q ? mkU128(imm) : mkU64(imm));
3849            if (U) {
3850               switch (size) {
3851                  case 0:
3852                     op = Q ? Iop_Shl8x16 : Iop_Shl8x8;
3853                     op_add = Q ? Iop_Add8x16 : Iop_Add8x8;
3854                     op_shrn = Q ? Iop_ShrN8x16 : Iop_ShrN8x8;
3855                     op_shln = Q ? Iop_ShlN8x16 : Iop_ShlN8x8;
3856                     break;
3857                  case 1:
3858                     op = Q ? Iop_Shl16x8 : Iop_Shl16x4;
3859                     op_add = Q ? Iop_Add16x8 : Iop_Add16x4;
3860                     op_shrn = Q ? Iop_ShrN16x8 : Iop_ShrN16x4;
3861                     op_shln = Q ? Iop_ShlN16x8 : Iop_ShlN16x4;
3862                     break;
3863                  case 2:
3864                     op = Q ? Iop_Shl32x4 : Iop_Shl32x2;
3865                     op_add = Q ? Iop_Add32x4 : Iop_Add32x2;
3866                     op_shrn = Q ? Iop_ShrN32x4 : Iop_ShrN32x2;
3867                     op_shln = Q ? Iop_ShlN32x4 : Iop_ShlN32x2;
3868                     break;
3869                  case 3:
3870                     op = Q ? Iop_Shl64x2 : Iop_Shl64;
3871                     op_add = Q ? Iop_Add64x2 : Iop_Add64;
3872                     op_shrn = Q ? Iop_ShrN64x2 : Iop_Shr64;
3873                     op_shln = Q ? Iop_ShlN64x2 : Iop_Shl64;
3874                     break;
3875                  default:
3876                     vassert(0);
3877               }
3878            } else {
3879               switch (size) {
3880                  case 0:
3881                     op = Q ? Iop_Sal8x16 : Iop_Sal8x8;
3882                     op_add = Q ? Iop_Add8x16 : Iop_Add8x8;
3883                     op_shrn = Q ? Iop_ShrN8x16 : Iop_ShrN8x8;
3884                     op_shln = Q ? Iop_ShlN8x16 : Iop_ShlN8x8;
3885                     break;
3886                  case 1:
3887                     op = Q ? Iop_Sal16x8 : Iop_Sal16x4;
3888                     op_add = Q ? Iop_Add16x8 : Iop_Add16x4;
3889                     op_shrn = Q ? Iop_ShrN16x8 : Iop_ShrN16x4;
3890                     op_shln = Q ? Iop_ShlN16x8 : Iop_ShlN16x4;
3891                     break;
3892                  case 2:
3893                     op = Q ? Iop_Sal32x4 : Iop_Sal32x2;
3894                     op_add = Q ? Iop_Add32x4 : Iop_Add32x2;
3895                     op_shrn = Q ? Iop_ShrN32x4 : Iop_ShrN32x2;
3896                     op_shln = Q ? Iop_ShlN32x4 : Iop_ShlN32x2;
3897                     break;
3898                  case 3:
3899                     op = Q ? Iop_Sal64x2 : Iop_Sal64x1;
3900                     op_add = Q ? Iop_Add64x2 : Iop_Add64;
3901                     op_shrn = Q ? Iop_ShrN64x2 : Iop_Shr64;
3902                     op_shln = Q ? Iop_ShlN64x2 : Iop_Shl64;
3903                     break;
3904                  default:
3905                     vassert(0);
3906               }
3907            }
3908            if (Q) {
3909               shval = newTemp(Ity_V128);
3910            } else {
3911               shval = newTemp(Ity_I64);
3912            }
3913            /* Only least significant byte from second argument is used.
3914               Copy this byte to the whole vector element. */
3915            assign(shval, binop(op_shrn,
3916                                binop(op_shln,
3917                                       mkexpr(arg_n),
3918                                       mkU8((8 << size) - 8)),
3919                                mkU8((8 << size) - 8)));
3920            for (i = 0; i < size; i++) {
3921               old_shval = shval;
3922               shval = newTemp(Q ? Ity_V128 : Ity_I64);
3923               assign(shval, binop(Q ? Iop_OrV128 : Iop_Or64,
3924                                   mkexpr(old_shval),
3925                                   binop(op_shln,
3926                                         mkexpr(old_shval),
3927                                         mkU8(8 << i))));
3928            }
3929            /* Compute the result */
3930            if (!Q && size == 3 && U) {
3931               assign(round, binop(Q ? Iop_AndV128 : Iop_And64,
3932                                   binop(op,
3933                                         mkexpr(arg_m),
3934                                         unop(Iop_64to8,
3935                                              binop(op_add,
3936                                                    mkexpr(arg_n),
3937                                                    mkexpr(imm_val)))),
3938                                   binop(Q ? Iop_AndV128 : Iop_And64,
3939                                         mkexpr(imm_val),
3940                                         binop(cmp_gt,
3941                                               Q ? mkU128(0) : mkU64(0),
3942                                               mkexpr(arg_n)))));
3943               assign(res, binop(op_add,
3944                                 binop(op,
3945                                       mkexpr(arg_m),
3946                                       unop(Iop_64to8, mkexpr(arg_n))),
3947                                 mkexpr(round)));
3948            } else {
3949               assign(round, binop(Q ? Iop_AndV128 : Iop_And64,
3950                                   binop(op,
3951                                         mkexpr(arg_m),
3952                                         binop(op_add,
3953                                               mkexpr(arg_n),
3954                                               mkexpr(imm_val))),
3955                                   binop(Q ? Iop_AndV128 : Iop_And64,
3956                                         mkexpr(imm_val),
3957                                         binop(cmp_gt,
3958                                               Q ? mkU128(0) : mkU64(0),
3959                                               mkexpr(arg_n)))));
3960               assign(res, binop(op_add,
3961                                 binop(op, mkexpr(arg_m), mkexpr(arg_n)),
3962                                 mkexpr(round)));
3963            }
3964            DIP("vrshl.%c%u %c%u, %c%u, %c%u\n",
3965                U ? 'u' : 's', 8 << size,
3966                Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg, Q ? 'q' : 'd',
3967                nreg);
3968         } else {
3969            /* VQRSHL */
3970            IROp op, op_rev, op_shrn, op_shln, cmp_neq, cmp_gt, op_add;
3971            IRTemp tmp, shval, mask, old_shval, imm_val, round;
3972            UInt i;
3973            ULong esize, imm;
3974            cmp_neq = Q ? Iop_CmpNEZ8x16 : Iop_CmpNEZ8x8;
3975            cmp_gt = Q ? Iop_CmpGT8Sx16 : Iop_CmpGT8Sx8;
3976            imm = 1L;
3977            switch (size) {
3978               case 0: imm = (imm <<  8) | imm; /* fall through */
3979               case 1: imm = (imm << 16) | imm; /* fall through */
3980               case 2: imm = (imm << 32) | imm; /* fall through */
3981               case 3: break;
3982               default: vassert(0);
3983            }
3984            imm_val = newTemp(Q ? Ity_V128 : Ity_I64);
3985            round = newTemp(Q ? Ity_V128 : Ity_I64);
3986            assign(imm_val, Q ? mkU128(imm) : mkU64(imm));
3987            if (U) {
3988               switch (size) {
3989                  case 0:
3990                     op = Q ? Iop_QShl8x16 : Iop_QShl8x8;
3991                     op_add = Q ? Iop_Add8x16 : Iop_Add8x8;
3992                     op_rev = Q ? Iop_Shr8x16 : Iop_Shr8x8;
3993                     op_shrn = Q ? Iop_ShrN8x16 : Iop_ShrN8x8;
3994                     op_shln = Q ? Iop_ShlN8x16 : Iop_ShlN8x8;
3995                     break;
3996                  case 1:
3997                     op = Q ? Iop_QShl16x8 : Iop_QShl16x4;
3998                     op_add = Q ? Iop_Add16x8 : Iop_Add16x4;
3999                     op_rev = Q ? Iop_Shr16x8 : Iop_Shr16x4;
4000                     op_shrn = Q ? Iop_ShrN16x8 : Iop_ShrN16x4;
4001                     op_shln = Q ? Iop_ShlN16x8 : Iop_ShlN16x4;
4002                     break;
4003                  case 2:
4004                     op = Q ? Iop_QShl32x4 : Iop_QShl32x2;
4005                     op_add = Q ? Iop_Add32x4 : Iop_Add32x2;
4006                     op_rev = Q ? Iop_Shr32x4 : Iop_Shr32x2;
4007                     op_shrn = Q ? Iop_ShrN32x4 : Iop_ShrN32x2;
4008                     op_shln = Q ? Iop_ShlN32x4 : Iop_ShlN32x2;
4009                     break;
4010                  case 3:
4011                     op = Q ? Iop_QShl64x2 : Iop_QShl64x1;
4012                     op_add = Q ? Iop_Add64x2 : Iop_Add64;
4013                     op_rev = Q ? Iop_Shr64x2 : Iop_Shr64;
4014                     op_shrn = Q ? Iop_ShrN64x2 : Iop_Shr64;
4015                     op_shln = Q ? Iop_ShlN64x2 : Iop_Shl64;
4016                     break;
4017                  default:
4018                     vassert(0);
4019               }
4020            } else {
4021               switch (size) {
4022                  case 0:
4023                     op = Q ? Iop_QSal8x16 : Iop_QSal8x8;
4024                     op_add = Q ? Iop_Add8x16 : Iop_Add8x8;
4025                     op_rev = Q ? Iop_Sar8x16 : Iop_Sar8x8;
4026                     op_shrn = Q ? Iop_ShrN8x16 : Iop_ShrN8x8;
4027                     op_shln = Q ? Iop_ShlN8x16 : Iop_ShlN8x8;
4028                     break;
4029                  case 1:
4030                     op = Q ? Iop_QSal16x8 : Iop_QSal16x4;
4031                     op_add = Q ? Iop_Add16x8 : Iop_Add16x4;
4032                     op_rev = Q ? Iop_Sar16x8 : Iop_Sar16x4;
4033                     op_shrn = Q ? Iop_ShrN16x8 : Iop_ShrN16x4;
4034                     op_shln = Q ? Iop_ShlN16x8 : Iop_ShlN16x4;
4035                     break;
4036                  case 2:
4037                     op = Q ? Iop_QSal32x4 : Iop_QSal32x2;
4038                     op_add = Q ? Iop_Add32x4 : Iop_Add32x2;
4039                     op_rev = Q ? Iop_Sar32x4 : Iop_Sar32x2;
4040                     op_shrn = Q ? Iop_ShrN32x4 : Iop_ShrN32x2;
4041                     op_shln = Q ? Iop_ShlN32x4 : Iop_ShlN32x2;
4042                     break;
4043                  case 3:
4044                     op = Q ? Iop_QSal64x2 : Iop_QSal64x1;
4045                     op_add = Q ? Iop_Add64x2 : Iop_Add64;
4046                     op_rev = Q ? Iop_Sar64x2 : Iop_Sar64;
4047                     op_shrn = Q ? Iop_ShrN64x2 : Iop_Shr64;
4048                     op_shln = Q ? Iop_ShlN64x2 : Iop_Shl64;
4049                     break;
4050                  default:
4051                     vassert(0);
4052               }
4053            }
4054            if (Q) {
4055               tmp = newTemp(Ity_V128);
4056               shval = newTemp(Ity_V128);
4057               mask = newTemp(Ity_V128);
4058            } else {
4059               tmp = newTemp(Ity_I64);
4060               shval = newTemp(Ity_I64);
4061               mask = newTemp(Ity_I64);
4062            }
4063            /* Only least significant byte from second argument is used.
4064               Copy this byte to the whole vector element. */
4065            assign(shval, binop(op_shrn,
4066                                binop(op_shln,
4067                                       mkexpr(arg_n),
4068                                       mkU8((8 << size) - 8)),
4069                                mkU8((8 << size) - 8)));
4070            for (i = 0; i < size; i++) {
4071               old_shval = shval;
4072               shval = newTemp(Q ? Ity_V128 : Ity_I64);
4073               assign(shval, binop(Q ? Iop_OrV128 : Iop_Or64,
4074                                   mkexpr(old_shval),
4075                                   binop(op_shln,
4076                                         mkexpr(old_shval),
4077                                         mkU8(8 << i))));
4078            }
4079            /* Compute the result */
4080            assign(round, binop(Q ? Iop_AndV128 : Iop_And64,
4081                                binop(op,
4082                                      mkexpr(arg_m),
4083                                      binop(op_add,
4084                                            mkexpr(arg_n),
4085                                            mkexpr(imm_val))),
4086                                binop(Q ? Iop_AndV128 : Iop_And64,
4087                                      mkexpr(imm_val),
4088                                      binop(cmp_gt,
4089                                            Q ? mkU128(0) : mkU64(0),
4090                                            mkexpr(arg_n)))));
4091            assign(res, binop(op_add,
4092                              binop(op, mkexpr(arg_m), mkexpr(arg_n)),
4093                              mkexpr(round)));
4094#ifndef DISABLE_QC_FLAG
4095            /* If shift is greater or equal to the element size and element is
4096               non-zero, then QC flag should be set. */
4097            esize = (8 << size) - 1;
4098            esize = (esize <<  8) | esize;
4099            esize = (esize << 16) | esize;
4100            esize = (esize << 32) | esize;
4101            setFlag_QC(binop(Q ? Iop_AndV128 : Iop_And64,
4102                             binop(cmp_gt, mkexpr(shval),
4103                                           Q ? mkU128(esize) : mkU64(esize)),
4104                             unop(cmp_neq, mkexpr(arg_m))),
4105                       Q ? mkU128(0) : mkU64(0),
4106                       Q, condT);
4107            /* Othervise QC flag should be set if shift value is positive and
4108               result beign rightshifted the same value is not equal to left
4109               argument. */
4110            assign(mask, binop(cmp_gt, mkexpr(shval),
4111                               Q ? mkU128(0) : mkU64(0)));
4112            if (!Q && size == 3)
4113               assign(tmp, binop(op_rev, mkexpr(res),
4114                                         unop(Iop_64to8, mkexpr(arg_n))));
4115            else
4116               assign(tmp, binop(op_rev, mkexpr(res), mkexpr(arg_n)));
4117            setFlag_QC(binop(Q ? Iop_AndV128 : Iop_And64,
4118                             mkexpr(tmp), mkexpr(mask)),
4119                       binop(Q ? Iop_AndV128 : Iop_And64,
4120                             mkexpr(arg_m), mkexpr(mask)),
4121                       Q, condT);
4122#endif
4123            DIP("vqrshl.%c%u %c%u, %c%u, %c%u\n",
4124                U ? 'u' : 's', 8 << size,
4125                Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg, Q ? 'q' : 'd',
4126                nreg);
4127         }
4128         break;
4129      case 6:
4130         /* VMAX, VMIN  */
4131         if (B == 0) {
4132            /* VMAX */
4133            IROp op;
4134            if (U == 0) {
4135               switch (size) {
4136                  case 0: op = Q ? Iop_Max8Sx16 : Iop_Max8Sx8; break;
4137                  case 1: op = Q ? Iop_Max16Sx8 : Iop_Max16Sx4; break;
4138                  case 2: op = Q ? Iop_Max32Sx4 : Iop_Max32Sx2; break;
4139                  case 3: return False;
4140                  default: vassert(0);
4141               }
4142            } else {
4143               switch (size) {
4144                  case 0: op = Q ? Iop_Max8Ux16 : Iop_Max8Ux8; break;
4145                  case 1: op = Q ? Iop_Max16Ux8 : Iop_Max16Ux4; break;
4146                  case 2: op = Q ? Iop_Max32Ux4 : Iop_Max32Ux2; break;
4147                  case 3: return False;
4148                  default: vassert(0);
4149               }
4150            }
4151            assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m)));
4152            DIP("vmax.%c%u %c%u, %c%u, %c%u\n",
4153                U ? 'u' : 's', 8 << size,
4154                Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', nreg, Q ? 'q' : 'd',
4155                mreg);
4156         } else {
4157            /* VMIN */
4158            IROp op;
4159            if (U == 0) {
4160               switch (size) {
4161                  case 0: op = Q ? Iop_Min8Sx16 : Iop_Min8Sx8; break;
4162                  case 1: op = Q ? Iop_Min16Sx8 : Iop_Min16Sx4; break;
4163                  case 2: op = Q ? Iop_Min32Sx4 : Iop_Min32Sx2; break;
4164                  case 3: return False;
4165                  default: vassert(0);
4166               }
4167            } else {
4168               switch (size) {
4169                  case 0: op = Q ? Iop_Min8Ux16 : Iop_Min8Ux8; break;
4170                  case 1: op = Q ? Iop_Min16Ux8 : Iop_Min16Ux4; break;
4171                  case 2: op = Q ? Iop_Min32Ux4 : Iop_Min32Ux2; break;
4172                  case 3: return False;
4173                  default: vassert(0);
4174               }
4175            }
4176            assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m)));
4177            DIP("vmin.%c%u %c%u, %c%u, %c%u\n",
4178                U ? 'u' : 's', 8 << size,
4179                Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', nreg, Q ? 'q' : 'd',
4180                mreg);
4181         }
4182         break;
4183      case 7:
4184         if (B == 0) {
4185            /* VABD */
4186            IROp op_cmp, op_sub;
4187            IRTemp cond;
4188            if ((theInstr >> 23) & 1) {
4189               vpanic("VABDL should not be in dis_neon_data_3same\n");
4190            }
4191            if (Q) {
4192               switch (size) {
4193                  case 0:
4194                     op_cmp = U ? Iop_CmpGT8Ux16 : Iop_CmpGT8Sx16;
4195                     op_sub = Iop_Sub8x16;
4196                     break;
4197                  case 1:
4198                     op_cmp = U ? Iop_CmpGT16Ux8 : Iop_CmpGT16Sx8;
4199                     op_sub = Iop_Sub16x8;
4200                     break;
4201                  case 2:
4202                     op_cmp = U ? Iop_CmpGT32Ux4 : Iop_CmpGT32Sx4;
4203                     op_sub = Iop_Sub32x4;
4204                     break;
4205                  case 3:
4206                     return False;
4207                  default:
4208                     vassert(0);
4209               }
4210            } else {
4211               switch (size) {
4212                  case 0:
4213                     op_cmp = U ? Iop_CmpGT8Ux8 : Iop_CmpGT8Sx8;
4214                     op_sub = Iop_Sub8x8;
4215                     break;
4216                  case 1:
4217                     op_cmp = U ? Iop_CmpGT16Ux4 : Iop_CmpGT16Sx4;
4218                     op_sub = Iop_Sub16x4;
4219                     break;
4220                  case 2:
4221                     op_cmp = U ? Iop_CmpGT32Ux2 : Iop_CmpGT32Sx2;
4222                     op_sub = Iop_Sub32x2;
4223                     break;
4224                  case 3:
4225                     return False;
4226                  default:
4227                     vassert(0);
4228               }
4229            }
4230            if (Q) {
4231               cond = newTemp(Ity_V128);
4232            } else {
4233               cond = newTemp(Ity_I64);
4234            }
4235            assign(cond, binop(op_cmp, mkexpr(arg_n), mkexpr(arg_m)));
4236            assign(res, binop(Q ? Iop_OrV128 : Iop_Or64,
4237                              binop(Q ? Iop_AndV128 : Iop_And64,
4238                                    binop(op_sub, mkexpr(arg_n),
4239                                                  mkexpr(arg_m)),
4240                                    mkexpr(cond)),
4241                              binop(Q ? Iop_AndV128 : Iop_And64,
4242                                    binop(op_sub, mkexpr(arg_m),
4243                                                  mkexpr(arg_n)),
4244                                    unop(Q ? Iop_NotV128 : Iop_Not64,
4245                                         mkexpr(cond)))));
4246            DIP("vabd.%c%u %c%u, %c%u, %c%u\n",
4247                U ? 'u' : 's', 8 << size,
4248                Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', nreg, Q ? 'q' : 'd',
4249                mreg);
4250         } else {
4251            /* VABA */
4252            IROp op_cmp, op_sub, op_add;
4253            IRTemp cond, acc, tmp;
4254            if ((theInstr >> 23) & 1) {
4255               vpanic("VABAL should not be in dis_neon_data_3same");
4256            }
4257            if (Q) {
4258               switch (size) {
4259                  case 0:
4260                     op_cmp = U ? Iop_CmpGT8Ux16 : Iop_CmpGT8Sx16;
4261                     op_sub = Iop_Sub8x16;
4262                     op_add = Iop_Add8x16;
4263                     break;
4264                  case 1:
4265                     op_cmp = U ? Iop_CmpGT16Ux8 : Iop_CmpGT16Sx8;
4266                     op_sub = Iop_Sub16x8;
4267                     op_add = Iop_Add16x8;
4268                     break;
4269                  case 2:
4270                     op_cmp = U ? Iop_CmpGT32Ux4 : Iop_CmpGT32Sx4;
4271                     op_sub = Iop_Sub32x4;
4272                     op_add = Iop_Add32x4;
4273                     break;
4274                  case 3:
4275                     return False;
4276                  default:
4277                     vassert(0);
4278               }
4279            } else {
4280               switch (size) {
4281                  case 0:
4282                     op_cmp = U ? Iop_CmpGT8Ux8 : Iop_CmpGT8Sx8;
4283                     op_sub = Iop_Sub8x8;
4284                     op_add = Iop_Add8x8;
4285                     break;
4286                  case 1:
4287                     op_cmp = U ? Iop_CmpGT16Ux4 : Iop_CmpGT16Sx4;
4288                     op_sub = Iop_Sub16x4;
4289                     op_add = Iop_Add16x4;
4290                     break;
4291                  case 2:
4292                     op_cmp = U ? Iop_CmpGT32Ux2 : Iop_CmpGT32Sx2;
4293                     op_sub = Iop_Sub32x2;
4294                     op_add = Iop_Add32x2;
4295                     break;
4296                  case 3:
4297                     return False;
4298                  default:
4299                     vassert(0);
4300               }
4301            }
4302            if (Q) {
4303               cond = newTemp(Ity_V128);
4304               acc = newTemp(Ity_V128);
4305               tmp = newTemp(Ity_V128);
4306               assign(acc, getQReg(dreg));
4307            } else {
4308               cond = newTemp(Ity_I64);
4309               acc = newTemp(Ity_I64);
4310               tmp = newTemp(Ity_I64);
4311               assign(acc, getDRegI64(dreg));
4312            }
4313            assign(cond, binop(op_cmp, mkexpr(arg_n), mkexpr(arg_m)));
4314            assign(tmp, binop(Q ? Iop_OrV128 : Iop_Or64,
4315                              binop(Q ? Iop_AndV128 : Iop_And64,
4316                                    binop(op_sub, mkexpr(arg_n),
4317                                                  mkexpr(arg_m)),
4318                                    mkexpr(cond)),
4319                              binop(Q ? Iop_AndV128 : Iop_And64,
4320                                    binop(op_sub, mkexpr(arg_m),
4321                                                  mkexpr(arg_n)),
4322                                    unop(Q ? Iop_NotV128 : Iop_Not64,
4323                                         mkexpr(cond)))));
4324            assign(res, binop(op_add, mkexpr(acc), mkexpr(tmp)));
4325            DIP("vaba.%c%u %c%u, %c%u, %c%u\n",
4326                U ? 'u' : 's', 8 << size,
4327                Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', nreg, Q ? 'q' : 'd',
4328                mreg);
4329         }
4330         break;
4331      case 8:
4332         if (B == 0) {
4333            IROp op;
4334            if (U == 0) {
4335               /* VADD  */
4336               switch (size) {
4337                  case 0: op = Q ? Iop_Add8x16 : Iop_Add8x8; break;
4338                  case 1: op = Q ? Iop_Add16x8 : Iop_Add16x4; break;
4339                  case 2: op = Q ? Iop_Add32x4 : Iop_Add32x2; break;
4340                  case 3: op = Q ? Iop_Add64x2 : Iop_Add64; break;
4341                  default: vassert(0);
4342               }
4343               DIP("vadd.i%u %c%u, %c%u, %c%u\n",
4344                   8 << size, Q ? 'q' : 'd',
4345                   dreg, Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg);
4346            } else {
4347               /* VSUB  */
4348               switch (size) {
4349                  case 0: op = Q ? Iop_Sub8x16 : Iop_Sub8x8; break;
4350                  case 1: op = Q ? Iop_Sub16x8 : Iop_Sub16x4; break;
4351                  case 2: op = Q ? Iop_Sub32x4 : Iop_Sub32x2; break;
4352                  case 3: op = Q ? Iop_Sub64x2 : Iop_Sub64; break;
4353                  default: vassert(0);
4354               }
4355               DIP("vsub.i%u %c%u, %c%u, %c%u\n",
4356                   8 << size, Q ? 'q' : 'd',
4357                   dreg, Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg);
4358            }
4359            assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m)));
4360         } else {
4361            IROp op;
4362            switch (size) {
4363               case 0: op = Q ? Iop_CmpNEZ8x16 : Iop_CmpNEZ8x8; break;
4364               case 1: op = Q ? Iop_CmpNEZ16x8 : Iop_CmpNEZ16x4; break;
4365               case 2: op = Q ? Iop_CmpNEZ32x4 : Iop_CmpNEZ32x2; break;
4366               case 3: op = Q ? Iop_CmpNEZ64x2 : Iop_CmpwNEZ64; break;
4367               default: vassert(0);
4368            }
4369            if (U == 0) {
4370               /* VTST  */
4371               assign(res, unop(op, binop(Q ? Iop_AndV128 : Iop_And64,
4372                                          mkexpr(arg_n),
4373                                          mkexpr(arg_m))));
4374               DIP("vtst.%u %c%u, %c%u, %c%u\n",
4375                   8 << size, Q ? 'q' : 'd',
4376                   dreg, Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg);
4377            } else {
4378               /* VCEQ  */
4379               assign(res, unop(Q ? Iop_NotV128 : Iop_Not64,
4380                                unop(op,
4381                                     binop(Q ? Iop_XorV128 : Iop_Xor64,
4382                                           mkexpr(arg_n),
4383                                           mkexpr(arg_m)))));
4384               DIP("vceq.i%u %c%u, %c%u, %c%u\n",
4385                   8 << size, Q ? 'q' : 'd',
4386                   dreg, Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg);
4387            }
4388         }
4389         break;
4390      case 9:
4391         if (B == 0) {
4392            /* VMLA, VMLS (integer) */
4393            IROp op, op2;
4394            UInt P = (theInstr >> 24) & 1;
4395            if (P) {
4396               switch (size) {
4397                  case 0:
4398                     op = Q ? Iop_Mul8x16 : Iop_Mul8x8;
4399                     op2 = Q ? Iop_Sub8x16 : Iop_Sub8x8;
4400                     break;
4401                  case 1:
4402                     op = Q ? Iop_Mul16x8 : Iop_Mul16x4;
4403                     op2 = Q ? Iop_Sub16x8 : Iop_Sub16x4;
4404                     break;
4405                  case 2:
4406                     op = Q ? Iop_Mul32x4 : Iop_Mul32x2;
4407                     op2 = Q ? Iop_Sub32x4 : Iop_Sub32x2;
4408                     break;
4409                  case 3:
4410                     return False;
4411                  default:
4412                     vassert(0);
4413               }
4414            } else {
4415               switch (size) {
4416                  case 0:
4417                     op = Q ? Iop_Mul8x16 : Iop_Mul8x8;
4418                     op2 = Q ? Iop_Add8x16 : Iop_Add8x8;
4419                     break;
4420                  case 1:
4421                     op = Q ? Iop_Mul16x8 : Iop_Mul16x4;
4422                     op2 = Q ? Iop_Add16x8 : Iop_Add16x4;
4423                     break;
4424                  case 2:
4425                     op = Q ? Iop_Mul32x4 : Iop_Mul32x2;
4426                     op2 = Q ? Iop_Add32x4 : Iop_Add32x2;
4427                     break;
4428                  case 3:
4429                     return False;
4430                  default:
4431                     vassert(0);
4432               }
4433            }
4434            assign(res, binop(op2,
4435                              Q ? getQReg(dreg) : getDRegI64(dreg),
4436                              binop(op, mkexpr(arg_n), mkexpr(arg_m))));
4437            DIP("vml%c.i%u %c%u, %c%u, %c%u\n",
4438                P ? 's' : 'a', 8 << size,
4439                Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', nreg, Q ? 'q' : 'd',
4440                mreg);
4441         } else {
4442            /* VMUL */
4443            IROp op;
4444            UInt P = (theInstr >> 24) & 1;
4445            if (P) {
4446               switch (size) {
4447                  case 0:
4448                     op = Q ? Iop_PolynomialMul8x16 : Iop_PolynomialMul8x8;
4449                     break;
4450                  case 1: case 2: case 3: return False;
4451                  default: vassert(0);
4452               }
4453            } else {
4454               switch (size) {
4455                  case 0: op = Q ? Iop_Mul8x16 : Iop_Mul8x8; break;
4456                  case 1: op = Q ? Iop_Mul16x8 : Iop_Mul16x4; break;
4457                  case 2: op = Q ? Iop_Mul32x4 : Iop_Mul32x2; break;
4458                  case 3: return False;
4459                  default: vassert(0);
4460               }
4461            }
4462            assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m)));
4463            DIP("vmul.%c%u %c%u, %c%u, %c%u\n",
4464                P ? 'p' : 'i', 8 << size,
4465                Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', nreg, Q ? 'q' : 'd',
4466                mreg);
4467         }
4468         break;
4469      case 10: {
4470         /* VPMAX, VPMIN  */
4471         UInt P = (theInstr >> 4) & 1;
4472         IROp op;
4473         if (Q)
4474            return False;
4475         if (P) {
4476            switch (size) {
4477               case 0: op = U ? Iop_PwMin8Ux8  : Iop_PwMin8Sx8; break;
4478               case 1: op = U ? Iop_PwMin16Ux4 : Iop_PwMin16Sx4; break;
4479               case 2: op = U ? Iop_PwMin32Ux2 : Iop_PwMin32Sx2; break;
4480               case 3: return False;
4481               default: vassert(0);
4482            }
4483         } else {
4484            switch (size) {
4485               case 0: op = U ? Iop_PwMax8Ux8  : Iop_PwMax8Sx8; break;
4486               case 1: op = U ? Iop_PwMax16Ux4 : Iop_PwMax16Sx4; break;
4487               case 2: op = U ? Iop_PwMax32Ux2 : Iop_PwMax32Sx2; break;
4488               case 3: return False;
4489               default: vassert(0);
4490            }
4491         }
4492         assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m)));
4493         DIP("vp%s.%c%u %c%u, %c%u, %c%u\n",
4494             P ? "min" : "max", U ? 'u' : 's',
4495             8 << size, Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', nreg,
4496             Q ? 'q' : 'd', mreg);
4497         break;
4498      }
4499      case 11:
4500         if (B == 0) {
4501            if (U == 0) {
4502               /* VQDMULH  */
4503               IROp op ,op2;
4504               ULong imm;
4505               switch (size) {
4506                  case 0: case 3:
4507                     return False;
4508                  case 1:
4509                     op = Q ? Iop_QDMulHi16Sx8 : Iop_QDMulHi16Sx4;
4510                     op2 = Q ? Iop_CmpEQ16x8 : Iop_CmpEQ16x4;
4511                     imm = 1LL << 15;
4512                     imm = (imm << 16) | imm;
4513                     imm = (imm << 32) | imm;
4514                     break;
4515                  case 2:
4516                     op = Q ? Iop_QDMulHi32Sx4 : Iop_QDMulHi32Sx2;
4517                     op2 = Q ? Iop_CmpEQ32x4 : Iop_CmpEQ32x2;
4518                     imm = 1LL << 31;
4519                     imm = (imm << 32) | imm;
4520                     break;
4521                  default:
4522                     vassert(0);
4523               }
4524               assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m)));
4525#ifndef DISABLE_QC_FLAG
4526               setFlag_QC(binop(Q ? Iop_AndV128 : Iop_And64,
4527                                binop(op2, mkexpr(arg_n),
4528                                           Q ? mkU128(imm) : mkU64(imm)),
4529                                binop(op2, mkexpr(arg_m),
4530                                           Q ? mkU128(imm) : mkU64(imm))),
4531                          Q ? mkU128(0) : mkU64(0),
4532                          Q, condT);
4533#endif
4534               DIP("vqdmulh.s%u %c%u, %c%u, %c%u\n",
4535                   8 << size, Q ? 'q' : 'd',
4536                   dreg, Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg);
4537            } else {
4538               /* VQRDMULH */
4539               IROp op ,op2;
4540               ULong imm;
4541               switch(size) {
4542                  case 0: case 3:
4543                     return False;
4544                  case 1:
4545                     imm = 1LL << 15;
4546                     imm = (imm << 16) | imm;
4547                     imm = (imm << 32) | imm;
4548                     op = Q ? Iop_QRDMulHi16Sx8 : Iop_QRDMulHi16Sx4;
4549                     op2 = Q ? Iop_CmpEQ16x8 : Iop_CmpEQ16x4;
4550                     break;
4551                  case 2:
4552                     imm = 1LL << 31;
4553                     imm = (imm << 32) | imm;
4554                     op = Q ? Iop_QRDMulHi32Sx4 : Iop_QRDMulHi32Sx2;
4555                     op2 = Q ? Iop_CmpEQ32x4 : Iop_CmpEQ32x2;
4556                     break;
4557                  default:
4558                     vassert(0);
4559               }
4560               assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m)));
4561#ifndef DISABLE_QC_FLAG
4562               setFlag_QC(binop(Q ? Iop_AndV128 : Iop_And64,
4563                                binop(op2, mkexpr(arg_n),
4564                                           Q ? mkU128(imm) : mkU64(imm)),
4565                                binop(op2, mkexpr(arg_m),
4566                                           Q ? mkU128(imm) : mkU64(imm))),
4567                          Q ? mkU128(0) : mkU64(0),
4568                          Q, condT);
4569#endif
4570               DIP("vqrdmulh.s%u %c%u, %c%u, %c%u\n",
4571                   8 << size, Q ? 'q' : 'd',
4572                   dreg, Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg);
4573            }
4574         } else {
4575            if (U == 0) {
4576               /* VPADD */
4577               IROp op;
4578               if (Q)
4579                  return False;
4580               switch (size) {
4581                  case 0: op = Q ? Iop_PwAdd8x16 : Iop_PwAdd8x8;  break;
4582                  case 1: op = Q ? Iop_PwAdd16x8 : Iop_PwAdd16x4; break;
4583                  case 2: op = Q ? Iop_PwAdd32x4 : Iop_PwAdd32x2; break;
4584                  case 3: return False;
4585                  default: vassert(0);
4586               }
4587               assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m)));
4588               DIP("vpadd.i%d %c%u, %c%u, %c%u\n",
4589                   8 << size, Q ? 'q' : 'd',
4590                   dreg, Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg);
4591            }
4592         }
4593         break;
4594      /* Starting from here these are FP SIMD cases */
4595      case 13:
4596         if (B == 0) {
4597            IROp op;
4598            if (U == 0) {
4599               if ((C >> 1) == 0) {
4600                  /* VADD  */
4601                  op = Q ? Iop_Add32Fx4 : Iop_Add32Fx2 ;
4602                  DIP("vadd.f32 %c%u, %c%u, %c%u\n",
4603                      Q ? 'q' : 'd', dreg,
4604                      Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg);
4605               } else {
4606                  /* VSUB  */
4607                  op = Q ? Iop_Sub32Fx4 : Iop_Sub32Fx2 ;
4608                  DIP("vsub.f32 %c%u, %c%u, %c%u\n",
4609                      Q ? 'q' : 'd', dreg,
4610                      Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg);
4611               }
4612            } else {
4613               if ((C >> 1) == 0) {
4614                  /* VPADD */
4615                  if (Q)
4616                     return False;
4617                  op = Iop_PwAdd32Fx2;
4618                  DIP("vpadd.f32 d%u, d%u, d%u\n", dreg, nreg, mreg);
4619               } else {
4620                  /* VABD  */
4621                  if (Q) {
4622                     assign(res, unop(Iop_Abs32Fx4,
4623                                      binop(Iop_Sub32Fx4,
4624                                            mkexpr(arg_n),
4625                                            mkexpr(arg_m))));
4626                  } else {
4627                     assign(res, unop(Iop_Abs32Fx2,
4628                                      binop(Iop_Sub32Fx2,
4629                                            mkexpr(arg_n),
4630                                            mkexpr(arg_m))));
4631                  }
4632                  DIP("vabd.f32 %c%u, %c%u, %c%u\n",
4633                      Q ? 'q' : 'd', dreg,
4634                      Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg);
4635                  break;
4636               }
4637            }
4638            assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m)));
4639         } else {
4640            if (U == 0) {
4641               /* VMLA, VMLS  */
4642               IROp op, op2;
4643               UInt P = (theInstr >> 21) & 1;
4644               if (P) {
4645                  switch (size & 1) {
4646                     case 0:
4647                        op = Q ? Iop_Mul32Fx4 : Iop_Mul32Fx2;
4648                        op2 = Q ? Iop_Sub32Fx4 : Iop_Sub32Fx2;
4649                        break;
4650                     case 1: return False;
4651                     default: vassert(0);
4652                  }
4653               } else {
4654                  switch (size & 1) {
4655                     case 0:
4656                        op = Q ? Iop_Mul32Fx4 : Iop_Mul32Fx2;
4657                        op2 = Q ? Iop_Add32Fx4 : Iop_Add32Fx2;
4658                        break;
4659                     case 1: return False;
4660                     default: vassert(0);
4661                  }
4662               }
4663               assign(res, binop(op2,
4664                                 Q ? getQReg(dreg) : getDRegI64(dreg),
4665                                 binop(op, mkexpr(arg_n), mkexpr(arg_m))));
4666
4667               DIP("vml%c.f32 %c%u, %c%u, %c%u\n",
4668                   P ? 's' : 'a', Q ? 'q' : 'd',
4669                   dreg, Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg);
4670            } else {
4671               /* VMUL  */
4672               IROp op;
4673               if ((C >> 1) != 0)
4674                  return False;
4675               op = Q ? Iop_Mul32Fx4 : Iop_Mul32Fx2 ;
4676               assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m)));
4677               DIP("vmul.f32 %c%u, %c%u, %c%u\n",
4678                   Q ? 'q' : 'd', dreg,
4679                   Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg);
4680            }
4681         }
4682         break;
4683      case 14:
4684         if (B == 0) {
4685            if (U == 0) {
4686               if ((C >> 1) == 0) {
4687                  /* VCEQ  */
4688                  IROp op;
4689                  if ((theInstr >> 20) & 1)
4690                     return False;
4691                  op = Q ? Iop_CmpEQ32Fx4 : Iop_CmpEQ32Fx2;
4692                  assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m)));
4693                  DIP("vceq.f32 %c%u, %c%u, %c%u\n",
4694                      Q ? 'q' : 'd', dreg,
4695                      Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg);
4696               } else {
4697                  return False;
4698               }
4699            } else {
4700               if ((C >> 1) == 0) {
4701                  /* VCGE  */
4702                  IROp op;
4703                  if ((theInstr >> 20) & 1)
4704                     return False;
4705                  op = Q ? Iop_CmpGE32Fx4 : Iop_CmpGE32Fx2;
4706                  assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m)));
4707                  DIP("vcge.f32 %c%u, %c%u, %c%u\n",
4708                      Q ? 'q' : 'd', dreg,
4709                      Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg);
4710               } else {
4711                  /* VCGT  */
4712                  IROp op;
4713                  if ((theInstr >> 20) & 1)
4714                     return False;
4715                  op = Q ? Iop_CmpGT32Fx4 : Iop_CmpGT32Fx2;
4716                  assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m)));
4717                  DIP("vcgt.f32 %c%u, %c%u, %c%u\n",
4718                      Q ? 'q' : 'd', dreg,
4719                      Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg);
4720               }
4721            }
4722         } else {
4723            if (U == 1) {
4724               /* VACGE, VACGT */
4725               UInt op_bit = (theInstr >> 21) & 1;
4726               IROp op, op2;
4727               op2 = Q ? Iop_Abs32Fx4 : Iop_Abs32Fx2;
4728               if (op_bit) {
4729                  op = Q ? Iop_CmpGT32Fx4 : Iop_CmpGT32Fx2;
4730                  assign(res, binop(op,
4731                                    unop(op2, mkexpr(arg_n)),
4732                                    unop(op2, mkexpr(arg_m))));
4733               } else {
4734                  op = Q ? Iop_CmpGE32Fx4 : Iop_CmpGE32Fx2;
4735                  assign(res, binop(op,
4736                                    unop(op2, mkexpr(arg_n)),
4737                                    unop(op2, mkexpr(arg_m))));
4738               }
4739               DIP("vacg%c.f32 %c%u, %c%u, %c%u\n", op_bit ? 't' : 'e',
4740                   Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', nreg,
4741                   Q ? 'q' : 'd', mreg);
4742            }
4743         }
4744         break;
4745      case 15:
4746         if (B == 0) {
4747            if (U == 0) {
4748               /* VMAX, VMIN  */
4749               IROp op;
4750               if ((theInstr >> 20) & 1)
4751                  return False;
4752               if ((theInstr >> 21) & 1) {
4753                  op = Q ? Iop_Min32Fx4 : Iop_Min32Fx2;
4754                  DIP("vmin.f32 %c%u, %c%u, %c%u\n", Q ? 'q' : 'd', dreg,
4755                      Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg);
4756               } else {
4757                  op = Q ? Iop_Max32Fx4 : Iop_Max32Fx2;
4758                  DIP("vmax.f32 %c%u, %c%u, %c%u\n", Q ? 'q' : 'd', dreg,
4759                      Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg);
4760               }
4761               assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m)));
4762            } else {
4763               /* VPMAX, VPMIN   */
4764               IROp op;
4765               if (Q)
4766                  return False;
4767               if ((theInstr >> 20) & 1)
4768                  return False;
4769               if ((theInstr >> 21) & 1) {
4770                  op = Iop_PwMin32Fx2;
4771                  DIP("vpmin.f32 d%u, d%u, d%u\n", dreg, nreg, mreg);
4772               } else {
4773                  op = Iop_PwMax32Fx2;
4774                  DIP("vpmax.f32 d%u, d%u, d%u\n", dreg, nreg, mreg);
4775               }
4776               assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m)));
4777            }
4778         } else {
4779            if (U == 0) {
4780               if ((C >> 1) == 0) {
4781                  /* VRECPS */
4782                  if ((theInstr >> 20) & 1)
4783                     return False;
4784                  assign(res, binop(Q ? Iop_Recps32Fx4 : Iop_Recps32Fx2,
4785                                    mkexpr(arg_n),
4786                                    mkexpr(arg_m)));
4787                  DIP("vrecps.f32 %c%u, %c%u, %c%u\n", Q ? 'q' : 'd', dreg,
4788                      Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg);
4789               } else {
4790                  /* VRSQRTS  */
4791                  if ((theInstr >> 20) & 1)
4792                     return False;
4793                  assign(res, binop(Q ? Iop_Rsqrts32Fx4 : Iop_Rsqrts32Fx2,
4794                                    mkexpr(arg_n),
4795                                    mkexpr(arg_m)));
4796                  DIP("vrsqrts.f32 %c%u, %c%u, %c%u\n", Q ? 'q' : 'd', dreg,
4797                      Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg);
4798               }
4799            }
4800         }
4801         break;
4802   }
4803
4804   if (Q) {
4805      putQReg(dreg, mkexpr(res), condT);
4806   } else {
4807      putDRegI64(dreg, mkexpr(res), condT);
4808   }
4809
4810   return True;
4811}
4812
4813/* A7.4.2 Three registers of different length */
4814static
4815Bool dis_neon_data_3diff ( UInt theInstr, IRTemp condT )
4816{
4817   UInt A = (theInstr >> 8) & 0xf;
4818   UInt B = (theInstr >> 20) & 3;
4819   UInt U = (theInstr >> 24) & 1;
4820   UInt P = (theInstr >> 9) & 1;
4821   UInt mreg = get_neon_m_regno(theInstr);
4822   UInt nreg = get_neon_n_regno(theInstr);
4823   UInt dreg = get_neon_d_regno(theInstr);
4824   UInt size = B;
4825   ULong imm;
4826   IRTemp res, arg_m, arg_n, cond, tmp;
4827   IROp cvt, cvt2, cmp, op, op2, sh, add;
4828   switch (A) {
4829      case 0: case 1: case 2: case 3:
4830         /* VADDL, VADDW, VSUBL, VSUBW */
4831         if (dreg & 1)
4832            return False;
4833         dreg >>= 1;
4834         size = B;
4835         switch (size) {
4836            case 0:
4837               cvt = U ? Iop_Widen8Uto16x8 : Iop_Widen8Sto16x8;
4838               op = (A & 2) ? Iop_Sub16x8 : Iop_Add16x8;
4839               break;
4840            case 1:
4841               cvt = U ? Iop_Widen16Uto32x4 : Iop_Widen16Sto32x4;
4842               op = (A & 2) ? Iop_Sub32x4 : Iop_Add32x4;
4843               break;
4844            case 2:
4845               cvt = U ? Iop_Widen32Uto64x2 : Iop_Widen32Sto64x2;
4846               op = (A & 2) ? Iop_Sub64x2 : Iop_Add64x2;
4847               break;
4848            case 3:
4849               return False;
4850            default:
4851               vassert(0);
4852         }
4853         arg_n = newTemp(Ity_V128);
4854         arg_m = newTemp(Ity_V128);
4855         if (A & 1) {
4856            if (nreg & 1)
4857               return False;
4858            nreg >>= 1;
4859            assign(arg_n, getQReg(nreg));
4860         } else {
4861            assign(arg_n, unop(cvt, getDRegI64(nreg)));
4862         }
4863         assign(arg_m, unop(cvt, getDRegI64(mreg)));
4864         putQReg(dreg, binop(op, mkexpr(arg_n), mkexpr(arg_m)),
4865                       condT);
4866         DIP("v%s%c.%c%u q%u, %c%u, d%u\n", (A & 2) ? "sub" : "add",
4867             (A & 1) ? 'w' : 'l', U ? 'u' : 's', 8 << size, dreg,
4868             (A & 1) ? 'q' : 'd', nreg, mreg);
4869         return True;
4870      case 4:
4871         /* VADDHN, VRADDHN */
4872         if (mreg & 1)
4873            return False;
4874         mreg >>= 1;
4875         if (nreg & 1)
4876            return False;
4877         nreg >>= 1;
4878         size = B;
4879         switch (size) {
4880            case 0:
4881               op = Iop_Add16x8;
4882               cvt = Iop_NarrowUn16to8x8;
4883               sh = Iop_ShrN16x8;
4884               imm = 1U << 7;
4885               imm = (imm << 16) | imm;
4886               imm = (imm << 32) | imm;
4887               break;
4888            case 1:
4889               op = Iop_Add32x4;
4890               cvt = Iop_NarrowUn32to16x4;
4891               sh = Iop_ShrN32x4;
4892               imm = 1U << 15;
4893               imm = (imm << 32) | imm;
4894               break;
4895            case 2:
4896               op = Iop_Add64x2;
4897               cvt = Iop_NarrowUn64to32x2;
4898               sh = Iop_ShrN64x2;
4899               imm = 1U << 31;
4900               break;
4901            case 3:
4902               return False;
4903            default:
4904               vassert(0);
4905         }
4906         tmp = newTemp(Ity_V128);
4907         res = newTemp(Ity_V128);
4908         assign(tmp, binop(op, getQReg(nreg), getQReg(mreg)));
4909         if (U) {
4910            /* VRADDHN */
4911            assign(res, binop(op, mkexpr(tmp),
4912                     binop(Iop_64HLtoV128, mkU64(imm), mkU64(imm))));
4913         } else {
4914            assign(res, mkexpr(tmp));
4915         }
4916         putDRegI64(dreg, unop(cvt, binop(sh, mkexpr(res), mkU8(8 << size))),
4917                    condT);
4918         DIP("v%saddhn.i%u d%u, q%u, q%u\n", U ? "r" : "", 16 << size, dreg,
4919             nreg, mreg);
4920         return True;
4921      case 5:
4922         /* VABAL */
4923         if (!((theInstr >> 23) & 1)) {
4924            vpanic("VABA should not be in dis_neon_data_3diff\n");
4925         }
4926         if (dreg & 1)
4927            return False;
4928         dreg >>= 1;
4929         switch (size) {
4930            case 0:
4931               cmp = U ? Iop_CmpGT8Ux8 : Iop_CmpGT8Sx8;
4932               cvt = U ? Iop_Widen8Uto16x8 : Iop_Widen8Sto16x8;
4933               cvt2 = Iop_Widen8Sto16x8;
4934               op = Iop_Sub16x8;
4935               op2 = Iop_Add16x8;
4936               break;
4937            case 1:
4938               cmp = U ? Iop_CmpGT16Ux4 : Iop_CmpGT16Sx4;
4939               cvt = U ? Iop_Widen16Uto32x4 : Iop_Widen16Sto32x4;
4940               cvt2 = Iop_Widen16Sto32x4;
4941               op = Iop_Sub32x4;
4942               op2 = Iop_Add32x4;
4943               break;
4944            case 2:
4945               cmp = U ? Iop_CmpGT32Ux2 : Iop_CmpGT32Sx2;
4946               cvt = U ? Iop_Widen32Uto64x2 : Iop_Widen32Sto64x2;
4947               cvt2 = Iop_Widen32Sto64x2;
4948               op = Iop_Sub64x2;
4949               op2 = Iop_Add64x2;
4950               break;
4951            case 3:
4952               return False;
4953            default:
4954               vassert(0);
4955         }
4956         arg_n = newTemp(Ity_V128);
4957         arg_m = newTemp(Ity_V128);
4958         cond = newTemp(Ity_V128);
4959         res = newTemp(Ity_V128);
4960         assign(arg_n, unop(cvt, getDRegI64(nreg)));
4961         assign(arg_m, unop(cvt, getDRegI64(mreg)));
4962         assign(cond, unop(cvt2, binop(cmp, getDRegI64(nreg),
4963                                            getDRegI64(mreg))));
4964         assign(res, binop(op2,
4965                           binop(Iop_OrV128,
4966                                 binop(Iop_AndV128,
4967                                       binop(op, mkexpr(arg_n), mkexpr(arg_m)),
4968                                       mkexpr(cond)),
4969                                 binop(Iop_AndV128,
4970                                       binop(op, mkexpr(arg_m), mkexpr(arg_n)),
4971                                       unop(Iop_NotV128, mkexpr(cond)))),
4972                           getQReg(dreg)));
4973         putQReg(dreg, mkexpr(res), condT);
4974         DIP("vabal.%c%u q%u, d%u, d%u\n", U ? 'u' : 's', 8 << size, dreg,
4975             nreg, mreg);
4976         return True;
4977      case 6:
4978         /* VSUBHN, VRSUBHN */
4979         if (mreg & 1)
4980            return False;
4981         mreg >>= 1;
4982         if (nreg & 1)
4983            return False;
4984         nreg >>= 1;
4985         size = B;
4986         switch (size) {
4987            case 0:
4988               op = Iop_Sub16x8;
4989               op2 = Iop_Add16x8;
4990               cvt = Iop_NarrowUn16to8x8;
4991               sh = Iop_ShrN16x8;
4992               imm = 1U << 7;
4993               imm = (imm << 16) | imm;
4994               imm = (imm << 32) | imm;
4995               break;
4996            case 1:
4997               op = Iop_Sub32x4;
4998               op2 = Iop_Add32x4;
4999               cvt = Iop_NarrowUn32to16x4;
5000               sh = Iop_ShrN32x4;
5001               imm = 1U << 15;
5002               imm = (imm << 32) | imm;
5003               break;
5004            case 2:
5005               op = Iop_Sub64x2;
5006               op2 = Iop_Add64x2;
5007               cvt = Iop_NarrowUn64to32x2;
5008               sh = Iop_ShrN64x2;
5009               imm = 1U << 31;
5010               break;
5011            case 3:
5012               return False;
5013            default:
5014               vassert(0);
5015         }
5016         tmp = newTemp(Ity_V128);
5017         res = newTemp(Ity_V128);
5018         assign(tmp, binop(op, getQReg(nreg), getQReg(mreg)));
5019         if (U) {
5020            /* VRSUBHN */
5021            assign(res, binop(op2, mkexpr(tmp),
5022                     binop(Iop_64HLtoV128, mkU64(imm), mkU64(imm))));
5023         } else {
5024            assign(res, mkexpr(tmp));
5025         }
5026         putDRegI64(dreg, unop(cvt, binop(sh, mkexpr(res), mkU8(8 << size))),
5027                    condT);
5028         DIP("v%ssubhn.i%u d%u, q%u, q%u\n", U ? "r" : "", 16 << size, dreg,
5029             nreg, mreg);
5030         return True;
5031      case 7:
5032         /* VABDL */
5033         if (!((theInstr >> 23) & 1)) {
5034            vpanic("VABL should not be in dis_neon_data_3diff\n");
5035         }
5036         if (dreg & 1)
5037            return False;
5038         dreg >>= 1;
5039         switch (size) {
5040            case 0:
5041               cmp = U ? Iop_CmpGT8Ux8 : Iop_CmpGT8Sx8;
5042               cvt = U ? Iop_Widen8Uto16x8 : Iop_Widen8Sto16x8;
5043               cvt2 = Iop_Widen8Sto16x8;
5044               op = Iop_Sub16x8;
5045               break;
5046            case 1:
5047               cmp = U ? Iop_CmpGT16Ux4 : Iop_CmpGT16Sx4;
5048               cvt = U ? Iop_Widen16Uto32x4 : Iop_Widen16Sto32x4;
5049               cvt2 = Iop_Widen16Sto32x4;
5050               op = Iop_Sub32x4;
5051               break;
5052            case 2:
5053               cmp = U ? Iop_CmpGT32Ux2 : Iop_CmpGT32Sx2;
5054               cvt = U ? Iop_Widen32Uto64x2 : Iop_Widen32Sto64x2;
5055               cvt2 = Iop_Widen32Sto64x2;
5056               op = Iop_Sub64x2;
5057               break;
5058            case 3:
5059               return False;
5060            default:
5061               vassert(0);
5062         }
5063         arg_n = newTemp(Ity_V128);
5064         arg_m = newTemp(Ity_V128);
5065         cond = newTemp(Ity_V128);
5066         res = newTemp(Ity_V128);
5067         assign(arg_n, unop(cvt, getDRegI64(nreg)));
5068         assign(arg_m, unop(cvt, getDRegI64(mreg)));
5069         assign(cond, unop(cvt2, binop(cmp, getDRegI64(nreg),
5070                                            getDRegI64(mreg))));
5071         assign(res, binop(Iop_OrV128,
5072                           binop(Iop_AndV128,
5073                                 binop(op, mkexpr(arg_n), mkexpr(arg_m)),
5074                                 mkexpr(cond)),
5075                           binop(Iop_AndV128,
5076                                 binop(op, mkexpr(arg_m), mkexpr(arg_n)),
5077                                 unop(Iop_NotV128, mkexpr(cond)))));
5078         putQReg(dreg, mkexpr(res), condT);
5079         DIP("vabdl.%c%u q%u, d%u, d%u\n", U ? 'u' : 's', 8 << size, dreg,
5080             nreg, mreg);
5081         return True;
5082      case 8:
5083      case 10:
5084         /* VMLAL, VMLSL (integer) */
5085         if (dreg & 1)
5086            return False;
5087         dreg >>= 1;
5088         size = B;
5089         switch (size) {
5090            case 0:
5091               op = U ? Iop_Mull8Ux8 : Iop_Mull8Sx8;
5092               op2 = P ? Iop_Sub16x8 : Iop_Add16x8;
5093               break;
5094            case 1:
5095               op = U ? Iop_Mull16Ux4 : Iop_Mull16Sx4;
5096               op2 = P ? Iop_Sub32x4 : Iop_Add32x4;
5097               break;
5098            case 2:
5099               op = U ? Iop_Mull32Ux2 : Iop_Mull32Sx2;
5100               op2 = P ? Iop_Sub64x2 : Iop_Add64x2;
5101               break;
5102            case 3:
5103               return False;
5104            default:
5105               vassert(0);
5106         }
5107         res = newTemp(Ity_V128);
5108         assign(res, binop(op, getDRegI64(nreg),getDRegI64(mreg)));
5109         putQReg(dreg, binop(op2, getQReg(dreg), mkexpr(res)), condT);
5110         DIP("vml%cl.%c%u q%u, d%u, d%u\n", P ? 's' : 'a', U ? 'u' : 's',
5111             8 << size, dreg, nreg, mreg);
5112         return True;
5113      case 9:
5114      case 11:
5115         /* VQDMLAL, VQDMLSL */
5116         if (U)
5117            return False;
5118         if (dreg & 1)
5119            return False;
5120         dreg >>= 1;
5121         size = B;
5122         switch (size) {
5123            case 0: case 3:
5124               return False;
5125            case 1:
5126               op = Iop_QDMulLong16Sx4;
5127               cmp = Iop_CmpEQ16x4;
5128               add = P ? Iop_QSub32Sx4 : Iop_QAdd32Sx4;
5129               op2 = P ? Iop_Sub32x4 : Iop_Add32x4;
5130               imm = 1LL << 15;
5131               imm = (imm << 16) | imm;
5132               imm = (imm << 32) | imm;
5133               break;
5134            case 2:
5135               op = Iop_QDMulLong32Sx2;
5136               cmp = Iop_CmpEQ32x2;
5137               add = P ? Iop_QSub64Sx2 : Iop_QAdd64Sx2;
5138               op2 = P ? Iop_Sub64x2 : Iop_Add64x2;
5139               imm = 1LL << 31;
5140               imm = (imm << 32) | imm;
5141               break;
5142            default:
5143               vassert(0);
5144         }
5145         res = newTemp(Ity_V128);
5146         tmp = newTemp(Ity_V128);
5147         assign(res, binop(op, getDRegI64(nreg), getDRegI64(mreg)));
5148#ifndef DISABLE_QC_FLAG
5149         assign(tmp, binop(op2, getQReg(dreg), mkexpr(res)));
5150         setFlag_QC(mkexpr(tmp), binop(add, getQReg(dreg), mkexpr(res)),
5151                    True, condT);
5152         setFlag_QC(binop(Iop_And64,
5153                          binop(cmp, getDRegI64(nreg), mkU64(imm)),
5154                          binop(cmp, getDRegI64(mreg), mkU64(imm))),
5155                    mkU64(0),
5156                    False, condT);
5157#endif
5158         putQReg(dreg, binop(add, getQReg(dreg), mkexpr(res)), condT);
5159         DIP("vqdml%cl.s%u q%u, d%u, d%u\n", P ? 's' : 'a', 8 << size, dreg,
5160             nreg, mreg);
5161         return True;
5162      case 12:
5163      case 14:
5164         /* VMULL (integer or polynomial) */
5165         if (dreg & 1)
5166            return False;
5167         dreg >>= 1;
5168         size = B;
5169         switch (size) {
5170            case 0:
5171               op = (U) ? Iop_Mull8Ux8 : Iop_Mull8Sx8;
5172               if (P)
5173                  op = Iop_PolynomialMull8x8;
5174               break;
5175            case 1:
5176               op = (U) ? Iop_Mull16Ux4 : Iop_Mull16Sx4;
5177               break;
5178            case 2:
5179               op = (U) ? Iop_Mull32Ux2 : Iop_Mull32Sx2;
5180               break;
5181            default:
5182               vassert(0);
5183         }
5184         putQReg(dreg, binop(op, getDRegI64(nreg),
5185                                 getDRegI64(mreg)), condT);
5186         DIP("vmull.%c%u q%u, d%u, d%u\n", P ? 'p' : (U ? 'u' : 's'),
5187               8 << size, dreg, nreg, mreg);
5188         return True;
5189      case 13:
5190         /* VQDMULL */
5191         if (U)
5192            return False;
5193         if (dreg & 1)
5194            return False;
5195         dreg >>= 1;
5196         size = B;
5197         switch (size) {
5198            case 0:
5199            case 3:
5200               return False;
5201            case 1:
5202               op = Iop_QDMulLong16Sx4;
5203               op2 = Iop_CmpEQ16x4;
5204               imm = 1LL << 15;
5205               imm = (imm << 16) | imm;
5206               imm = (imm << 32) | imm;
5207               break;
5208            case 2:
5209               op = Iop_QDMulLong32Sx2;
5210               op2 = Iop_CmpEQ32x2;
5211               imm = 1LL << 31;
5212               imm = (imm << 32) | imm;
5213               break;
5214            default:
5215               vassert(0);
5216         }
5217         putQReg(dreg, binop(op, getDRegI64(nreg), getDRegI64(mreg)),
5218               condT);
5219#ifndef DISABLE_QC_FLAG
5220         setFlag_QC(binop(Iop_And64,
5221                          binop(op2, getDRegI64(nreg), mkU64(imm)),
5222                          binop(op2, getDRegI64(mreg), mkU64(imm))),
5223                    mkU64(0),
5224                    False, condT);
5225#endif
5226         DIP("vqdmull.s%u q%u, d%u, d%u\n", 8 << size, dreg, nreg, mreg);
5227         return True;
5228      default:
5229         return False;
5230   }
5231   return False;
5232}
5233
5234/* A7.4.3 Two registers and a scalar */
5235static
5236Bool dis_neon_data_2reg_and_scalar ( UInt theInstr, IRTemp condT )
5237{
5238#  define INSN(_bMax,_bMin)  SLICE_UInt(theInstr, (_bMax), (_bMin))
5239   UInt U = INSN(24,24);
5240   UInt dreg = get_neon_d_regno(theInstr & ~(1 << 6));
5241   UInt nreg = get_neon_n_regno(theInstr & ~(1 << 6));
5242   UInt mreg = get_neon_m_regno(theInstr & ~(1 << 6));
5243   UInt size = INSN(21,20);
5244   UInt index;
5245   UInt Q = INSN(24,24);
5246
5247   if (INSN(27,25) != 1 || INSN(23,23) != 1
5248       || INSN(6,6) != 1 || INSN(4,4) != 0)
5249      return False;
5250
5251   /* VMLA, VMLS (scalar)  */
5252   if ((INSN(11,8) & BITS4(1,0,1,0)) == BITS4(0,0,0,0)) {
5253      IRTemp res, arg_m, arg_n;
5254      IROp dup, get, op, op2, add, sub;
5255      if (Q) {
5256         if ((dreg & 1) || (nreg & 1))
5257            return False;
5258         dreg >>= 1;
5259         nreg >>= 1;
5260         res = newTemp(Ity_V128);
5261         arg_m = newTemp(Ity_V128);
5262         arg_n = newTemp(Ity_V128);
5263         assign(arg_n, getQReg(nreg));
5264         switch(size) {
5265            case 1:
5266               dup = Iop_Dup16x8;
5267               get = Iop_GetElem16x4;
5268               index = mreg >> 3;
5269               mreg &= 7;
5270               break;
5271            case 2:
5272               dup = Iop_Dup32x4;
5273               get = Iop_GetElem32x2;
5274               index = mreg >> 4;
5275               mreg &= 0xf;
5276               break;
5277            case 0:
5278            case 3:
5279               return False;
5280            default:
5281               vassert(0);
5282         }
5283         assign(arg_m, unop(dup, binop(get, getDRegI64(mreg), mkU8(index))));
5284      } else {
5285         res = newTemp(Ity_I64);
5286         arg_m = newTemp(Ity_I64);
5287         arg_n = newTemp(Ity_I64);
5288         assign(arg_n, getDRegI64(nreg));
5289         switch(size) {
5290            case 1:
5291               dup = Iop_Dup16x4;
5292               get = Iop_GetElem16x4;
5293               index = mreg >> 3;
5294               mreg &= 7;
5295               break;
5296            case 2:
5297               dup = Iop_Dup32x2;
5298               get = Iop_GetElem32x2;
5299               index = mreg >> 4;
5300               mreg &= 0xf;
5301               break;
5302            case 0:
5303            case 3:
5304               return False;
5305            default:
5306               vassert(0);
5307         }
5308         assign(arg_m, unop(dup, binop(get, getDRegI64(mreg), mkU8(index))));
5309      }
5310      if (INSN(8,8)) {
5311         switch (size) {
5312            case 2:
5313               op = Q ? Iop_Mul32Fx4 : Iop_Mul32Fx2;
5314               add = Q ? Iop_Add32Fx4 : Iop_Add32Fx2;
5315               sub = Q ? Iop_Sub32Fx4 : Iop_Sub32Fx2;
5316               break;
5317            case 0:
5318            case 1:
5319            case 3:
5320               return False;
5321            default:
5322               vassert(0);
5323         }
5324      } else {
5325         switch (size) {
5326            case 1:
5327               op = Q ? Iop_Mul16x8 : Iop_Mul16x4;
5328               add = Q ? Iop_Add16x8 : Iop_Add16x4;
5329               sub = Q ? Iop_Sub16x8 : Iop_Sub16x4;
5330               break;
5331            case 2:
5332               op = Q ? Iop_Mul32x4 : Iop_Mul32x2;
5333               add = Q ? Iop_Add32x4 : Iop_Add32x2;
5334               sub = Q ? Iop_Sub32x4 : Iop_Sub32x2;
5335               break;
5336            case 0:
5337            case 3:
5338               return False;
5339            default:
5340               vassert(0);
5341         }
5342      }
5343      op2 = INSN(10,10) ? sub : add;
5344      assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m)));
5345      if (Q)
5346         putQReg(dreg, binop(op2, getQReg(dreg), mkexpr(res)),
5347               condT);
5348      else
5349         putDRegI64(dreg, binop(op2, getDRegI64(dreg), mkexpr(res)),
5350                    condT);
5351      DIP("vml%c.%c%u %c%u, %c%u, d%u[%u]\n", INSN(10,10) ? 's' : 'a',
5352            INSN(8,8) ? 'f' : 'i', 8 << size,
5353            Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', nreg, mreg, index);
5354      return True;
5355   }
5356
5357   /* VMLAL, VMLSL (scalar)   */
5358   if ((INSN(11,8) & BITS4(1,0,1,1)) == BITS4(0,0,1,0)) {
5359      IRTemp res, arg_m, arg_n;
5360      IROp dup, get, op, op2, add, sub;
5361      if (dreg & 1)
5362         return False;
5363      dreg >>= 1;
5364      res = newTemp(Ity_V128);
5365      arg_m = newTemp(Ity_I64);
5366      arg_n = newTemp(Ity_I64);
5367      assign(arg_n, getDRegI64(nreg));
5368      switch(size) {
5369         case 1:
5370            dup = Iop_Dup16x4;
5371            get = Iop_GetElem16x4;
5372            index = mreg >> 3;
5373            mreg &= 7;
5374            break;
5375         case 2:
5376            dup = Iop_Dup32x2;
5377            get = Iop_GetElem32x2;
5378            index = mreg >> 4;
5379            mreg &= 0xf;
5380            break;
5381         case 0:
5382         case 3:
5383            return False;
5384         default:
5385            vassert(0);
5386      }
5387      assign(arg_m, unop(dup, binop(get, getDRegI64(mreg), mkU8(index))));
5388      switch (size) {
5389         case 1:
5390            op = U ? Iop_Mull16Ux4 : Iop_Mull16Sx4;
5391            add = Iop_Add32x4;
5392            sub = Iop_Sub32x4;
5393            break;
5394         case 2:
5395            op = U ? Iop_Mull32Ux2 : Iop_Mull32Sx2;
5396            add = Iop_Add64x2;
5397            sub = Iop_Sub64x2;
5398            break;
5399         case 0:
5400         case 3:
5401            return False;
5402         default:
5403            vassert(0);
5404      }
5405      op2 = INSN(10,10) ? sub : add;
5406      assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m)));
5407      putQReg(dreg, binop(op2, getQReg(dreg), mkexpr(res)), condT);
5408      DIP("vml%cl.%c%u q%u, d%u, d%u[%u]\n",
5409          INSN(10,10) ? 's' : 'a', U ? 'u' : 's',
5410          8 << size, dreg, nreg, mreg, index);
5411      return True;
5412   }
5413
5414   /* VQDMLAL, VQDMLSL (scalar)  */
5415   if ((INSN(11,8) & BITS4(1,0,1,1)) == BITS4(0,0,1,1) && !U) {
5416      IRTemp res, arg_m, arg_n, tmp;
5417      IROp dup, get, op, op2, add, cmp;
5418      UInt P = INSN(10,10);
5419      ULong imm;
5420      if (dreg & 1)
5421         return False;
5422      dreg >>= 1;
5423      res = newTemp(Ity_V128);
5424      arg_m = newTemp(Ity_I64);
5425      arg_n = newTemp(Ity_I64);
5426      assign(arg_n, getDRegI64(nreg));
5427      switch(size) {
5428         case 1:
5429            dup = Iop_Dup16x4;
5430            get = Iop_GetElem16x4;
5431            index = mreg >> 3;
5432            mreg &= 7;
5433            break;
5434         case 2:
5435            dup = Iop_Dup32x2;
5436            get = Iop_GetElem32x2;
5437            index = mreg >> 4;
5438            mreg &= 0xf;
5439            break;
5440         case 0:
5441         case 3:
5442            return False;
5443         default:
5444            vassert(0);
5445      }
5446      assign(arg_m, unop(dup, binop(get, getDRegI64(mreg), mkU8(index))));
5447      switch (size) {
5448         case 0:
5449         case 3:
5450            return False;
5451         case 1:
5452            op = Iop_QDMulLong16Sx4;
5453            cmp = Iop_CmpEQ16x4;
5454            add = P ? Iop_QSub32Sx4 : Iop_QAdd32Sx4;
5455            op2 = P ? Iop_Sub32x4 : Iop_Add32x4;
5456            imm = 1LL << 15;
5457            imm = (imm << 16) | imm;
5458            imm = (imm << 32) | imm;
5459            break;
5460         case 2:
5461            op = Iop_QDMulLong32Sx2;
5462            cmp = Iop_CmpEQ32x2;
5463            add = P ? Iop_QSub64Sx2 : Iop_QAdd64Sx2;
5464            op2 = P ? Iop_Sub64x2 : Iop_Add64x2;
5465            imm = 1LL << 31;
5466            imm = (imm << 32) | imm;
5467            break;
5468         default:
5469            vassert(0);
5470      }
5471      res = newTemp(Ity_V128);
5472      tmp = newTemp(Ity_V128);
5473      assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m)));
5474#ifndef DISABLE_QC_FLAG
5475      assign(tmp, binop(op2, getQReg(dreg), mkexpr(res)));
5476      setFlag_QC(binop(Iop_And64,
5477                       binop(cmp, mkexpr(arg_n), mkU64(imm)),
5478                       binop(cmp, mkexpr(arg_m), mkU64(imm))),
5479                 mkU64(0),
5480                 False, condT);
5481      setFlag_QC(mkexpr(tmp), binop(add, getQReg(dreg), mkexpr(res)),
5482                 True, condT);
5483#endif
5484      putQReg(dreg, binop(add, getQReg(dreg), mkexpr(res)), condT);
5485      DIP("vqdml%cl.s%u q%u, d%u, d%u[%u]\n", P ? 's' : 'a', 8 << size,
5486          dreg, nreg, mreg, index);
5487      return True;
5488   }
5489
5490   /* VMUL (by scalar)  */
5491   if ((INSN(11,8) & BITS4(1,1,1,0)) == BITS4(1,0,0,0)) {
5492      IRTemp res, arg_m, arg_n;
5493      IROp dup, get, op;
5494      if (Q) {
5495         if ((dreg & 1) || (nreg & 1))
5496            return False;
5497         dreg >>= 1;
5498         nreg >>= 1;
5499         res = newTemp(Ity_V128);
5500         arg_m = newTemp(Ity_V128);
5501         arg_n = newTemp(Ity_V128);
5502         assign(arg_n, getQReg(nreg));
5503         switch(size) {
5504            case 1:
5505               dup = Iop_Dup16x8;
5506               get = Iop_GetElem16x4;
5507               index = mreg >> 3;
5508               mreg &= 7;
5509               break;
5510            case 2:
5511               dup = Iop_Dup32x4;
5512               get = Iop_GetElem32x2;
5513               index = mreg >> 4;
5514               mreg &= 0xf;
5515               break;
5516            case 0:
5517            case 3:
5518               return False;
5519            default:
5520               vassert(0);
5521         }
5522         assign(arg_m, unop(dup, binop(get, getDRegI64(mreg), mkU8(index))));
5523      } else {
5524         res = newTemp(Ity_I64);
5525         arg_m = newTemp(Ity_I64);
5526         arg_n = newTemp(Ity_I64);
5527         assign(arg_n, getDRegI64(nreg));
5528         switch(size) {
5529            case 1:
5530               dup = Iop_Dup16x4;
5531               get = Iop_GetElem16x4;
5532               index = mreg >> 3;
5533               mreg &= 7;
5534               break;
5535            case 2:
5536               dup = Iop_Dup32x2;
5537               get = Iop_GetElem32x2;
5538               index = mreg >> 4;
5539               mreg &= 0xf;
5540               break;
5541            case 0:
5542            case 3:
5543               return False;
5544            default:
5545               vassert(0);
5546         }
5547         assign(arg_m, unop(dup, binop(get, getDRegI64(mreg), mkU8(index))));
5548      }
5549      if (INSN(8,8)) {
5550         switch (size) {
5551            case 2:
5552               op = Q ? Iop_Mul32Fx4 : Iop_Mul32Fx2;
5553               break;
5554            case 0:
5555            case 1:
5556            case 3:
5557               return False;
5558            default:
5559               vassert(0);
5560         }
5561      } else {
5562         switch (size) {
5563            case 1:
5564               op = Q ? Iop_Mul16x8 : Iop_Mul16x4;
5565               break;
5566            case 2:
5567               op = Q ? Iop_Mul32x4 : Iop_Mul32x2;
5568               break;
5569            case 0:
5570            case 3:
5571               return False;
5572            default:
5573               vassert(0);
5574         }
5575      }
5576      assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m)));
5577      if (Q)
5578         putQReg(dreg, mkexpr(res), condT);
5579      else
5580         putDRegI64(dreg, mkexpr(res), condT);
5581      DIP("vmul.%c%u %c%u, %c%u, d%u[%u]\n", INSN(8,8) ? 'f' : 'i',
5582          8 << size, Q ? 'q' : 'd', dreg,
5583          Q ? 'q' : 'd', nreg, mreg, index);
5584      return True;
5585   }
5586
5587   /* VMULL (scalar) */
5588   if (INSN(11,8) == BITS4(1,0,1,0)) {
5589      IRTemp res, arg_m, arg_n;
5590      IROp dup, get, op;
5591      if (dreg & 1)
5592         return False;
5593      dreg >>= 1;
5594      res = newTemp(Ity_V128);
5595      arg_m = newTemp(Ity_I64);
5596      arg_n = newTemp(Ity_I64);
5597      assign(arg_n, getDRegI64(nreg));
5598      switch(size) {
5599         case 1:
5600            dup = Iop_Dup16x4;
5601            get = Iop_GetElem16x4;
5602            index = mreg >> 3;
5603            mreg &= 7;
5604            break;
5605         case 2:
5606            dup = Iop_Dup32x2;
5607            get = Iop_GetElem32x2;
5608            index = mreg >> 4;
5609            mreg &= 0xf;
5610            break;
5611         case 0:
5612         case 3:
5613            return False;
5614         default:
5615            vassert(0);
5616      }
5617      assign(arg_m, unop(dup, binop(get, getDRegI64(mreg), mkU8(index))));
5618      switch (size) {
5619         case 1: op = U ? Iop_Mull16Ux4 : Iop_Mull16Sx4; break;
5620         case 2: op = U ? Iop_Mull32Ux2 : Iop_Mull32Sx2; break;
5621         case 0: case 3: return False;
5622         default: vassert(0);
5623      }
5624      assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m)));
5625      putQReg(dreg, mkexpr(res), condT);
5626      DIP("vmull.%c%u q%u, d%u, d%u[%u]\n", U ? 'u' : 's', 8 << size, dreg,
5627          nreg, mreg, index);
5628      return True;
5629   }
5630
5631   /* VQDMULL */
5632   if (INSN(11,8) == BITS4(1,0,1,1) && !U) {
5633      IROp op ,op2, dup, get;
5634      ULong imm;
5635      IRTemp arg_m, arg_n;
5636      if (dreg & 1)
5637         return False;
5638      dreg >>= 1;
5639      arg_m = newTemp(Ity_I64);
5640      arg_n = newTemp(Ity_I64);
5641      assign(arg_n, getDRegI64(nreg));
5642      switch(size) {
5643         case 1:
5644            dup = Iop_Dup16x4;
5645            get = Iop_GetElem16x4;
5646            index = mreg >> 3;
5647            mreg &= 7;
5648            break;
5649         case 2:
5650            dup = Iop_Dup32x2;
5651            get = Iop_GetElem32x2;
5652            index = mreg >> 4;
5653            mreg &= 0xf;
5654            break;
5655         case 0:
5656         case 3:
5657            return False;
5658         default:
5659            vassert(0);
5660      }
5661      assign(arg_m, unop(dup, binop(get, getDRegI64(mreg), mkU8(index))));
5662      switch (size) {
5663         case 0:
5664         case 3:
5665            return False;
5666         case 1:
5667            op = Iop_QDMulLong16Sx4;
5668            op2 = Iop_CmpEQ16x4;
5669            imm = 1LL << 15;
5670            imm = (imm << 16) | imm;
5671            imm = (imm << 32) | imm;
5672            break;
5673         case 2:
5674            op = Iop_QDMulLong32Sx2;
5675            op2 = Iop_CmpEQ32x2;
5676            imm = 1LL << 31;
5677            imm = (imm << 32) | imm;
5678            break;
5679         default:
5680            vassert(0);
5681      }
5682      putQReg(dreg, binop(op, mkexpr(arg_n), mkexpr(arg_m)),
5683            condT);
5684#ifndef DISABLE_QC_FLAG
5685      setFlag_QC(binop(Iop_And64,
5686                       binop(op2, mkexpr(arg_n), mkU64(imm)),
5687                       binop(op2, mkexpr(arg_m), mkU64(imm))),
5688                 mkU64(0),
5689                 False, condT);
5690#endif
5691      DIP("vqdmull.s%u q%u, d%u, d%u[%u]\n", 8 << size, dreg, nreg, mreg,
5692          index);
5693      return True;
5694   }
5695
5696   /* VQDMULH */
5697   if (INSN(11,8) == BITS4(1,1,0,0)) {
5698      IROp op ,op2, dup, get;
5699      ULong imm;
5700      IRTemp res, arg_m, arg_n;
5701      if (Q) {
5702         if ((dreg & 1) || (nreg & 1))
5703            return False;
5704         dreg >>= 1;
5705         nreg >>= 1;
5706         res = newTemp(Ity_V128);
5707         arg_m = newTemp(Ity_V128);
5708         arg_n = newTemp(Ity_V128);
5709         assign(arg_n, getQReg(nreg));
5710         switch(size) {
5711            case 1:
5712               dup = Iop_Dup16x8;
5713               get = Iop_GetElem16x4;
5714               index = mreg >> 3;
5715               mreg &= 7;
5716               break;
5717            case 2:
5718               dup = Iop_Dup32x4;
5719               get = Iop_GetElem32x2;
5720               index = mreg >> 4;
5721               mreg &= 0xf;
5722               break;
5723            case 0:
5724            case 3:
5725               return False;
5726            default:
5727               vassert(0);
5728         }
5729         assign(arg_m, unop(dup, binop(get, getDRegI64(mreg), mkU8(index))));
5730      } else {
5731         res = newTemp(Ity_I64);
5732         arg_m = newTemp(Ity_I64);
5733         arg_n = newTemp(Ity_I64);
5734         assign(arg_n, getDRegI64(nreg));
5735         switch(size) {
5736            case 1:
5737               dup = Iop_Dup16x4;
5738               get = Iop_GetElem16x4;
5739               index = mreg >> 3;
5740               mreg &= 7;
5741               break;
5742            case 2:
5743               dup = Iop_Dup32x2;
5744               get = Iop_GetElem32x2;
5745               index = mreg >> 4;
5746               mreg &= 0xf;
5747               break;
5748            case 0:
5749            case 3:
5750               return False;
5751            default:
5752               vassert(0);
5753         }
5754         assign(arg_m, unop(dup, binop(get, getDRegI64(mreg), mkU8(index))));
5755      }
5756      switch (size) {
5757         case 0:
5758         case 3:
5759            return False;
5760         case 1:
5761            op = Q ? Iop_QDMulHi16Sx8 : Iop_QDMulHi16Sx4;
5762            op2 = Q ? Iop_CmpEQ16x8 : Iop_CmpEQ16x4;
5763            imm = 1LL << 15;
5764            imm = (imm << 16) | imm;
5765            imm = (imm << 32) | imm;
5766            break;
5767         case 2:
5768            op = Q ? Iop_QDMulHi32Sx4 : Iop_QDMulHi32Sx2;
5769            op2 = Q ? Iop_CmpEQ32x4 : Iop_CmpEQ32x2;
5770            imm = 1LL << 31;
5771            imm = (imm << 32) | imm;
5772            break;
5773         default:
5774            vassert(0);
5775      }
5776      assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m)));
5777#ifndef DISABLE_QC_FLAG
5778      setFlag_QC(binop(Q ? Iop_AndV128 : Iop_And64,
5779                       binop(op2, mkexpr(arg_n),
5780                                  Q ? mkU128(imm) : mkU64(imm)),
5781                       binop(op2, mkexpr(arg_m),
5782                             Q ? mkU128(imm) : mkU64(imm))),
5783                 Q ? mkU128(0) : mkU64(0),
5784                 Q, condT);
5785#endif
5786      if (Q)
5787         putQReg(dreg, mkexpr(res), condT);
5788      else
5789         putDRegI64(dreg, mkexpr(res), condT);
5790      DIP("vqdmulh.s%u %c%u, %c%u, d%u[%u]\n",
5791          8 << size, Q ? 'q' : 'd', dreg,
5792          Q ? 'q' : 'd', nreg, mreg, index);
5793      return True;
5794   }
5795
5796   /* VQRDMULH (scalar) */
5797   if (INSN(11,8) == BITS4(1,1,0,1)) {
5798      IROp op ,op2, dup, get;
5799      ULong imm;
5800      IRTemp res, arg_m, arg_n;
5801      if (Q) {
5802         if ((dreg & 1) || (nreg & 1))
5803            return False;
5804         dreg >>= 1;
5805         nreg >>= 1;
5806         res = newTemp(Ity_V128);
5807         arg_m = newTemp(Ity_V128);
5808         arg_n = newTemp(Ity_V128);
5809         assign(arg_n, getQReg(nreg));
5810         switch(size) {
5811            case 1:
5812               dup = Iop_Dup16x8;
5813               get = Iop_GetElem16x4;
5814               index = mreg >> 3;
5815               mreg &= 7;
5816               break;
5817            case 2:
5818               dup = Iop_Dup32x4;
5819               get = Iop_GetElem32x2;
5820               index = mreg >> 4;
5821               mreg &= 0xf;
5822               break;
5823            case 0:
5824            case 3:
5825               return False;
5826            default:
5827               vassert(0);
5828         }
5829         assign(arg_m, unop(dup, binop(get, getDRegI64(mreg), mkU8(index))));
5830      } else {
5831         res = newTemp(Ity_I64);
5832         arg_m = newTemp(Ity_I64);
5833         arg_n = newTemp(Ity_I64);
5834         assign(arg_n, getDRegI64(nreg));
5835         switch(size) {
5836            case 1:
5837               dup = Iop_Dup16x4;
5838               get = Iop_GetElem16x4;
5839               index = mreg >> 3;
5840               mreg &= 7;
5841               break;
5842            case 2:
5843               dup = Iop_Dup32x2;
5844               get = Iop_GetElem32x2;
5845               index = mreg >> 4;
5846               mreg &= 0xf;
5847               break;
5848            case 0:
5849            case 3:
5850               return False;
5851            default:
5852               vassert(0);
5853         }
5854         assign(arg_m, unop(dup, binop(get, getDRegI64(mreg), mkU8(index))));
5855      }
5856      switch (size) {
5857         case 0:
5858         case 3:
5859            return False;
5860         case 1:
5861            op = Q ? Iop_QRDMulHi16Sx8 : Iop_QRDMulHi16Sx4;
5862            op2 = Q ? Iop_CmpEQ16x8 : Iop_CmpEQ16x4;
5863            imm = 1LL << 15;
5864            imm = (imm << 16) | imm;
5865            imm = (imm << 32) | imm;
5866            break;
5867         case 2:
5868            op = Q ? Iop_QRDMulHi32Sx4 : Iop_QRDMulHi32Sx2;
5869            op2 = Q ? Iop_CmpEQ32x4 : Iop_CmpEQ32x2;
5870            imm = 1LL << 31;
5871            imm = (imm << 32) | imm;
5872            break;
5873         default:
5874            vassert(0);
5875      }
5876      assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m)));
5877#ifndef DISABLE_QC_FLAG
5878      setFlag_QC(binop(Q ? Iop_AndV128 : Iop_And64,
5879                       binop(op2, mkexpr(arg_n),
5880                                  Q ? mkU128(imm) : mkU64(imm)),
5881                       binop(op2, mkexpr(arg_m),
5882                                  Q ? mkU128(imm) : mkU64(imm))),
5883                 Q ? mkU128(0) : mkU64(0),
5884                 Q, condT);
5885#endif
5886      if (Q)
5887         putQReg(dreg, mkexpr(res), condT);
5888      else
5889         putDRegI64(dreg, mkexpr(res), condT);
5890      DIP("vqrdmulh.s%u %c%u, %c%u, d%u[%u]\n",
5891          8 << size, Q ? 'q' : 'd', dreg,
5892          Q ? 'q' : 'd', nreg, mreg, index);
5893      return True;
5894   }
5895
5896   return False;
5897#  undef INSN
5898}
5899
5900/* A7.4.4 Two registers and a shift amount */
5901static
5902Bool dis_neon_data_2reg_and_shift ( UInt theInstr, IRTemp condT )
5903{
5904   UInt A = (theInstr >> 8) & 0xf;
5905   UInt B = (theInstr >> 6) & 1;
5906   UInt L = (theInstr >> 7) & 1;
5907   UInt U = (theInstr >> 24) & 1;
5908   UInt Q = B;
5909   UInt imm6 = (theInstr >> 16) & 0x3f;
5910   UInt shift_imm;
5911   UInt size = 4;
5912   UInt tmp;
5913   UInt mreg = get_neon_m_regno(theInstr);
5914   UInt dreg = get_neon_d_regno(theInstr);
5915   ULong imm = 0;
5916   IROp op, cvt, add = Iop_INVALID, cvt2, op_rev;
5917   IRTemp reg_m, res, mask;
5918
5919   if (L == 0 && ((theInstr >> 19) & 7) == 0)
5920      /* It is one reg and immediate */
5921      return False;
5922
5923   tmp = (L << 6) | imm6;
5924   if (tmp & 0x40) {
5925      size = 3;
5926      shift_imm = 64 - imm6;
5927   } else if (tmp & 0x20) {
5928      size = 2;
5929      shift_imm = 64 - imm6;
5930   } else if (tmp & 0x10) {
5931      size = 1;
5932      shift_imm = 32 - imm6;
5933   } else if (tmp & 0x8) {
5934      size = 0;
5935      shift_imm = 16 - imm6;
5936   } else {
5937      return False;
5938   }
5939
5940   switch (A) {
5941      case 3:
5942      case 2:
5943         /* VRSHR, VRSRA */
5944         if (shift_imm > 0) {
5945            IRExpr *imm_val;
5946            imm = 1L;
5947            switch (size) {
5948               case 0:
5949                  imm = (imm << 8) | imm;
5950                  /* fall through */
5951               case 1:
5952                  imm = (imm << 16) | imm;
5953                  /* fall through */
5954               case 2:
5955                  imm = (imm << 32) | imm;
5956                  /* fall through */
5957               case 3:
5958                  break;
5959               default:
5960                  vassert(0);
5961            }
5962            if (Q) {
5963               reg_m = newTemp(Ity_V128);
5964               res = newTemp(Ity_V128);
5965               imm_val = binop(Iop_64HLtoV128, mkU64(imm), mkU64(imm));
5966               assign(reg_m, getQReg(mreg));
5967               switch (size) {
5968                  case 0:
5969                     add = Iop_Add8x16;
5970                     op = U ? Iop_ShrN8x16 : Iop_SarN8x16;
5971                     break;
5972                  case 1:
5973                     add = Iop_Add16x8;
5974                     op = U ? Iop_ShrN16x8 : Iop_SarN16x8;
5975                     break;
5976                  case 2:
5977                     add = Iop_Add32x4;
5978                     op = U ? Iop_ShrN32x4 : Iop_SarN32x4;
5979                     break;
5980                  case 3:
5981                     add = Iop_Add64x2;
5982                     op = U ? Iop_ShrN64x2 : Iop_SarN64x2;
5983                     break;
5984                  default:
5985                     vassert(0);
5986               }
5987            } else {
5988               reg_m = newTemp(Ity_I64);
5989               res = newTemp(Ity_I64);
5990               imm_val = mkU64(imm);
5991               assign(reg_m, getDRegI64(mreg));
5992               switch (size) {
5993                  case 0:
5994                     add = Iop_Add8x8;
5995                     op = U ? Iop_ShrN8x8 : Iop_SarN8x8;
5996                     break;
5997                  case 1:
5998                     add = Iop_Add16x4;
5999                     op = U ? Iop_ShrN16x4 : Iop_SarN16x4;
6000                     break;
6001                  case 2:
6002                     add = Iop_Add32x2;
6003                     op = U ? Iop_ShrN32x2 : Iop_SarN32x2;
6004                     break;
6005                  case 3:
6006                     add = Iop_Add64;
6007                     op = U ? Iop_Shr64 : Iop_Sar64;
6008                     break;
6009                  default:
6010                     vassert(0);
6011               }
6012            }
6013            assign(res,
6014                   binop(add,
6015                         binop(op,
6016                               mkexpr(reg_m),
6017                               mkU8(shift_imm)),
6018                         binop(Q ? Iop_AndV128 : Iop_And64,
6019                               binop(op,
6020                                     mkexpr(reg_m),
6021                                     mkU8(shift_imm - 1)),
6022                               imm_val)));
6023         } else {
6024            if (Q) {
6025               res = newTemp(Ity_V128);
6026               assign(res, getQReg(mreg));
6027            } else {
6028               res = newTemp(Ity_I64);
6029               assign(res, getDRegI64(mreg));
6030            }
6031         }
6032         if (A == 3) {
6033            if (Q) {
6034               putQReg(dreg, binop(add, mkexpr(res), getQReg(dreg)),
6035                             condT);
6036            } else {
6037               putDRegI64(dreg, binop(add, mkexpr(res), getDRegI64(dreg)),
6038                                condT);
6039            }
6040            DIP("vrsra.%c%u %c%u, %c%u, #%u\n",
6041                U ? 'u' : 's', 8 << size,
6042                Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg, shift_imm);
6043         } else {
6044            if (Q) {
6045               putQReg(dreg, mkexpr(res), condT);
6046            } else {
6047               putDRegI64(dreg, mkexpr(res), condT);
6048            }
6049            DIP("vrshr.%c%u %c%u, %c%u, #%u\n", U ? 'u' : 's', 8 << size,
6050                Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg, shift_imm);
6051         }
6052         return True;
6053      case 1:
6054      case 0:
6055         /* VSHR, VSRA */
6056         if (Q) {
6057            reg_m = newTemp(Ity_V128);
6058            assign(reg_m, getQReg(mreg));
6059            res = newTemp(Ity_V128);
6060         } else {
6061            reg_m = newTemp(Ity_I64);
6062            assign(reg_m, getDRegI64(mreg));
6063            res = newTemp(Ity_I64);
6064         }
6065         if (Q) {
6066            switch (size) {
6067               case 0:
6068                  op = U ? Iop_ShrN8x16 : Iop_SarN8x16;
6069                  add = Iop_Add8x16;
6070                  break;
6071               case 1:
6072                  op = U ? Iop_ShrN16x8 : Iop_SarN16x8;
6073                  add = Iop_Add16x8;
6074                  break;
6075               case 2:
6076                  op = U ? Iop_ShrN32x4 : Iop_SarN32x4;
6077                  add = Iop_Add32x4;
6078                  break;
6079               case 3:
6080                  op = U ? Iop_ShrN64x2 : Iop_SarN64x2;
6081                  add = Iop_Add64x2;
6082                  break;
6083               default:
6084                  vassert(0);
6085            }
6086         } else {
6087            switch (size) {
6088               case 0:
6089                  op =  U ? Iop_ShrN8x8 : Iop_SarN8x8;
6090                  add = Iop_Add8x8;
6091                  break;
6092               case 1:
6093                  op = U ? Iop_ShrN16x4 : Iop_SarN16x4;
6094                  add = Iop_Add16x4;
6095                  break;
6096               case 2:
6097                  op = U ? Iop_ShrN32x2 : Iop_SarN32x2;
6098                  add = Iop_Add32x2;
6099                  break;
6100               case 3:
6101                  op = U ? Iop_Shr64 : Iop_Sar64;
6102                  add = Iop_Add64;
6103                  break;
6104               default:
6105                  vassert(0);
6106            }
6107         }
6108         assign(res, binop(op, mkexpr(reg_m), mkU8(shift_imm)));
6109         if (A == 1) {
6110            if (Q) {
6111               putQReg(dreg, binop(add, mkexpr(res), getQReg(dreg)),
6112                             condT);
6113            } else {
6114               putDRegI64(dreg, binop(add, mkexpr(res), getDRegI64(dreg)),
6115                                condT);
6116            }
6117            DIP("vsra.%c%u %c%u, %c%u, #%u\n", U ? 'u' : 's', 8 << size,
6118                  Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg, shift_imm);
6119         } else {
6120            if (Q) {
6121               putQReg(dreg, mkexpr(res), condT);
6122            } else {
6123               putDRegI64(dreg, mkexpr(res), condT);
6124            }
6125            DIP("vshr.%c%u %c%u, %c%u, #%u\n", U ? 'u' : 's', 8 << size,
6126                  Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg, shift_imm);
6127         }
6128         return True;
6129      case 4:
6130         /* VSRI */
6131         if (!U)
6132            return False;
6133         if (Q) {
6134            res = newTemp(Ity_V128);
6135            mask = newTemp(Ity_V128);
6136         } else {
6137            res = newTemp(Ity_I64);
6138            mask = newTemp(Ity_I64);
6139         }
6140         switch (size) {
6141            case 0: op = Q ? Iop_ShrN8x16 : Iop_ShrN8x8; break;
6142            case 1: op = Q ? Iop_ShrN16x8 : Iop_ShrN16x4; break;
6143            case 2: op = Q ? Iop_ShrN32x4 : Iop_ShrN32x2; break;
6144            case 3: op = Q ? Iop_ShrN64x2 : Iop_Shr64; break;
6145            default: vassert(0);
6146         }
6147         if (Q) {
6148            assign(mask, binop(op, binop(Iop_64HLtoV128,
6149                                         mkU64(0xFFFFFFFFFFFFFFFFLL),
6150                                         mkU64(0xFFFFFFFFFFFFFFFFLL)),
6151                               mkU8(shift_imm)));
6152            assign(res, binop(Iop_OrV128,
6153                              binop(Iop_AndV128,
6154                                    getQReg(dreg),
6155                                    unop(Iop_NotV128,
6156                                         mkexpr(mask))),
6157                              binop(op,
6158                                    getQReg(mreg),
6159                                    mkU8(shift_imm))));
6160            putQReg(dreg, mkexpr(res), condT);
6161         } else {
6162            assign(mask, binop(op, mkU64(0xFFFFFFFFFFFFFFFFLL),
6163                               mkU8(shift_imm)));
6164            assign(res, binop(Iop_Or64,
6165                              binop(Iop_And64,
6166                                    getDRegI64(dreg),
6167                                    unop(Iop_Not64,
6168                                         mkexpr(mask))),
6169                              binop(op,
6170                                    getDRegI64(mreg),
6171                                    mkU8(shift_imm))));
6172            putDRegI64(dreg, mkexpr(res), condT);
6173         }
6174         DIP("vsri.%u %c%u, %c%u, #%u\n",
6175             8 << size, Q ? 'q' : 'd', dreg,
6176             Q ? 'q' : 'd', mreg, shift_imm);
6177         return True;
6178      case 5:
6179         if (U) {
6180            /* VSLI */
6181            shift_imm = 8 * (1 << size) - shift_imm;
6182            if (Q) {
6183               res = newTemp(Ity_V128);
6184               mask = newTemp(Ity_V128);
6185            } else {
6186               res = newTemp(Ity_I64);
6187               mask = newTemp(Ity_I64);
6188            }
6189            switch (size) {
6190               case 0: op = Q ? Iop_ShlN8x16 : Iop_ShlN8x8; break;
6191               case 1: op = Q ? Iop_ShlN16x8 : Iop_ShlN16x4; break;
6192               case 2: op = Q ? Iop_ShlN32x4 : Iop_ShlN32x2; break;
6193               case 3: op = Q ? Iop_ShlN64x2 : Iop_Shl64; break;
6194               default: vassert(0);
6195            }
6196            if (Q) {
6197               assign(mask, binop(op, binop(Iop_64HLtoV128,
6198                                            mkU64(0xFFFFFFFFFFFFFFFFLL),
6199                                            mkU64(0xFFFFFFFFFFFFFFFFLL)),
6200                                  mkU8(shift_imm)));
6201               assign(res, binop(Iop_OrV128,
6202                                 binop(Iop_AndV128,
6203                                       getQReg(dreg),
6204                                       unop(Iop_NotV128,
6205                                            mkexpr(mask))),
6206                                 binop(op,
6207                                       getQReg(mreg),
6208                                       mkU8(shift_imm))));
6209               putQReg(dreg, mkexpr(res), condT);
6210            } else {
6211               assign(mask, binop(op, mkU64(0xFFFFFFFFFFFFFFFFLL),
6212                                  mkU8(shift_imm)));
6213               assign(res, binop(Iop_Or64,
6214                                 binop(Iop_And64,
6215                                       getDRegI64(dreg),
6216                                       unop(Iop_Not64,
6217                                            mkexpr(mask))),
6218                                 binop(op,
6219                                       getDRegI64(mreg),
6220                                       mkU8(shift_imm))));
6221               putDRegI64(dreg, mkexpr(res), condT);
6222            }
6223            DIP("vsli.%u %c%u, %c%u, #%u\n",
6224                8 << size, Q ? 'q' : 'd', dreg,
6225                Q ? 'q' : 'd', mreg, shift_imm);
6226            return True;
6227         } else {
6228            /* VSHL #imm */
6229            shift_imm = 8 * (1 << size) - shift_imm;
6230            if (Q) {
6231               res = newTemp(Ity_V128);
6232            } else {
6233               res = newTemp(Ity_I64);
6234            }
6235            switch (size) {
6236               case 0: op = Q ? Iop_ShlN8x16 : Iop_ShlN8x8; break;
6237               case 1: op = Q ? Iop_ShlN16x8 : Iop_ShlN16x4; break;
6238               case 2: op = Q ? Iop_ShlN32x4 : Iop_ShlN32x2; break;
6239               case 3: op = Q ? Iop_ShlN64x2 : Iop_Shl64; break;
6240               default: vassert(0);
6241            }
6242            assign(res, binop(op, Q ? getQReg(mreg) : getDRegI64(mreg),
6243                     mkU8(shift_imm)));
6244            if (Q) {
6245               putQReg(dreg, mkexpr(res), condT);
6246            } else {
6247               putDRegI64(dreg, mkexpr(res), condT);
6248            }
6249            DIP("vshl.i%u %c%u, %c%u, #%u\n",
6250                8 << size, Q ? 'q' : 'd', dreg,
6251                Q ? 'q' : 'd', mreg, shift_imm);
6252            return True;
6253         }
6254         break;
6255      case 6:
6256      case 7:
6257         /* VQSHL, VQSHLU */
6258         shift_imm = 8 * (1 << size) - shift_imm;
6259         if (U) {
6260            if (A & 1) {
6261               switch (size) {
6262                  case 0:
6263                     op = Q ? Iop_QShlN8x16 : Iop_QShlN8x8;
6264                     op_rev = Q ? Iop_ShrN8x16 : Iop_ShrN8x8;
6265                     break;
6266                  case 1:
6267                     op = Q ? Iop_QShlN16x8 : Iop_QShlN16x4;
6268                     op_rev = Q ? Iop_ShrN16x8 : Iop_ShrN16x4;
6269                     break;
6270                  case 2:
6271                     op = Q ? Iop_QShlN32x4 : Iop_QShlN32x2;
6272                     op_rev = Q ? Iop_ShrN32x4 : Iop_ShrN32x2;
6273                     break;
6274                  case 3:
6275                     op = Q ? Iop_QShlN64x2 : Iop_QShlN64x1;
6276                     op_rev = Q ? Iop_ShrN64x2 : Iop_Shr64;
6277                     break;
6278                  default:
6279                     vassert(0);
6280               }
6281               DIP("vqshl.u%u %c%u, %c%u, #%u\n",
6282                   8 << size,
6283                   Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg, shift_imm);
6284            } else {
6285               switch (size) {
6286                  case 0:
6287                     op = Q ? Iop_QShlN8Sx16 : Iop_QShlN8Sx8;
6288                     op_rev = Q ? Iop_ShrN8x16 : Iop_ShrN8x8;
6289                     break;
6290                  case 1:
6291                     op = Q ? Iop_QShlN16Sx8 : Iop_QShlN16Sx4;
6292                     op_rev = Q ? Iop_ShrN16x8 : Iop_ShrN16x4;
6293                     break;
6294                  case 2:
6295                     op = Q ? Iop_QShlN32Sx4 : Iop_QShlN32Sx2;
6296                     op_rev = Q ? Iop_ShrN32x4 : Iop_ShrN32x2;
6297                     break;
6298                  case 3:
6299                     op = Q ? Iop_QShlN64Sx2 : Iop_QShlN64Sx1;
6300                     op_rev = Q ? Iop_ShrN64x2 : Iop_Shr64;
6301                     break;
6302                  default:
6303                     vassert(0);
6304               }
6305               DIP("vqshlu.s%u %c%u, %c%u, #%u\n",
6306                   8 << size,
6307                   Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg, shift_imm);
6308            }
6309         } else {
6310            if (!(A & 1))
6311               return False;
6312            switch (size) {
6313               case 0:
6314                  op = Q ? Iop_QSalN8x16 : Iop_QSalN8x8;
6315                  op_rev = Q ? Iop_SarN8x16 : Iop_SarN8x8;
6316                  break;
6317               case 1:
6318                  op = Q ? Iop_QSalN16x8 : Iop_QSalN16x4;
6319                  op_rev = Q ? Iop_SarN16x8 : Iop_SarN16x4;
6320                  break;
6321               case 2:
6322                  op = Q ? Iop_QSalN32x4 : Iop_QSalN32x2;
6323                  op_rev = Q ? Iop_SarN32x4 : Iop_SarN32x2;
6324                  break;
6325               case 3:
6326                  op = Q ? Iop_QSalN64x2 : Iop_QSalN64x1;
6327                  op_rev = Q ? Iop_SarN64x2 : Iop_Sar64;
6328                  break;
6329               default:
6330                  vassert(0);
6331            }
6332            DIP("vqshl.s%u %c%u, %c%u, #%u\n",
6333                8 << size,
6334                Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg, shift_imm);
6335         }
6336         if (Q) {
6337            tmp = newTemp(Ity_V128);
6338            res = newTemp(Ity_V128);
6339            reg_m = newTemp(Ity_V128);
6340            assign(reg_m, getQReg(mreg));
6341         } else {
6342            tmp = newTemp(Ity_I64);
6343            res = newTemp(Ity_I64);
6344            reg_m = newTemp(Ity_I64);
6345            assign(reg_m, getDRegI64(mreg));
6346         }
6347         assign(res, binop(op, mkexpr(reg_m), mkU8(shift_imm)));
6348#ifndef DISABLE_QC_FLAG
6349         assign(tmp, binop(op_rev, mkexpr(res), mkU8(shift_imm)));
6350         setFlag_QC(mkexpr(tmp), mkexpr(reg_m), Q, condT);
6351#endif
6352         if (Q)
6353            putQReg(dreg, mkexpr(res), condT);
6354         else
6355            putDRegI64(dreg, mkexpr(res), condT);
6356         return True;
6357      case 8:
6358         if (!U) {
6359            if (L == 1)
6360               return False;
6361            size++;
6362            dreg = ((theInstr >> 18) & 0x10) | ((theInstr >> 12) & 0xF);
6363            mreg = ((theInstr >> 1) & 0x10) | (theInstr & 0xF);
6364            if (mreg & 1)
6365               return False;
6366            mreg >>= 1;
6367            if (!B) {
6368               /* VSHRN*/
6369               IROp narOp;
6370               reg_m = newTemp(Ity_V128);
6371               assign(reg_m, getQReg(mreg));
6372               res = newTemp(Ity_I64);
6373               switch (size) {
6374                  case 1:
6375                     op = Iop_ShrN16x8;
6376                     narOp = Iop_NarrowUn16to8x8;
6377                     break;
6378                  case 2:
6379                     op = Iop_ShrN32x4;
6380                     narOp = Iop_NarrowUn32to16x4;
6381                     break;
6382                  case 3:
6383                     op = Iop_ShrN64x2;
6384                     narOp = Iop_NarrowUn64to32x2;
6385                     break;
6386                  default:
6387                     vassert(0);
6388               }
6389               assign(res, unop(narOp,
6390                                binop(op,
6391                                      mkexpr(reg_m),
6392                                      mkU8(shift_imm))));
6393               putDRegI64(dreg, mkexpr(res), condT);
6394               DIP("vshrn.i%u d%u, q%u, #%u\n", 8 << size, dreg, mreg,
6395                   shift_imm);
6396               return True;
6397            } else {
6398               /* VRSHRN   */
6399               IROp addOp, shOp, narOp;
6400               IRExpr *imm_val;
6401               reg_m = newTemp(Ity_V128);
6402               assign(reg_m, getQReg(mreg));
6403               res = newTemp(Ity_I64);
6404               imm = 1L;
6405               switch (size) {
6406                  case 0: imm = (imm <<  8) | imm; /* fall through */
6407                  case 1: imm = (imm << 16) | imm; /* fall through */
6408                  case 2: imm = (imm << 32) | imm; /* fall through */
6409                  case 3: break;
6410                  default: vassert(0);
6411               }
6412               imm_val = binop(Iop_64HLtoV128, mkU64(imm), mkU64(imm));
6413               switch (size) {
6414                  case 1:
6415                     addOp = Iop_Add16x8;
6416                     shOp = Iop_ShrN16x8;
6417                     narOp = Iop_NarrowUn16to8x8;
6418                     break;
6419                  case 2:
6420                     addOp = Iop_Add32x4;
6421                     shOp = Iop_ShrN32x4;
6422                     narOp = Iop_NarrowUn32to16x4;
6423                     break;
6424                  case 3:
6425                     addOp = Iop_Add64x2;
6426                     shOp = Iop_ShrN64x2;
6427                     narOp = Iop_NarrowUn64to32x2;
6428                     break;
6429                  default:
6430                     vassert(0);
6431               }
6432               assign(res, unop(narOp,
6433                                binop(addOp,
6434                                      binop(shOp,
6435                                            mkexpr(reg_m),
6436                                            mkU8(shift_imm)),
6437                                      binop(Iop_AndV128,
6438                                            binop(shOp,
6439                                                  mkexpr(reg_m),
6440                                                  mkU8(shift_imm - 1)),
6441                                            imm_val))));
6442               putDRegI64(dreg, mkexpr(res), condT);
6443               if (shift_imm == 0) {
6444                  DIP("vmov%u d%u, q%u, #%u\n", 8 << size, dreg, mreg,
6445                      shift_imm);
6446               } else {
6447                  DIP("vrshrn.i%u d%u, q%u, #%u\n", 8 << size, dreg, mreg,
6448                      shift_imm);
6449               }
6450               return True;
6451            }
6452         } else {
6453            /* fall through */
6454         }
6455      case 9:
6456         dreg = ((theInstr >> 18) & 0x10) | ((theInstr >> 12) & 0xF);
6457         mreg = ((theInstr >>  1) & 0x10) | (theInstr & 0xF);
6458         if (mreg & 1)
6459            return False;
6460         mreg >>= 1;
6461         size++;
6462         if ((theInstr >> 8) & 1) {
6463            switch (size) {
6464               case 1:
6465                  op = U ? Iop_ShrN16x8 : Iop_SarN16x8;
6466                  cvt = U ? Iop_QNarrowUn16Uto8Ux8 : Iop_QNarrowUn16Sto8Sx8;
6467                  cvt2 = U ? Iop_Widen8Uto16x8 : Iop_Widen8Sto16x8;
6468                  break;
6469               case 2:
6470                  op = U ? Iop_ShrN32x4 : Iop_SarN32x4;
6471                  cvt = U ? Iop_QNarrowUn32Uto16Ux4 : Iop_QNarrowUn32Sto16Sx4;
6472                  cvt2 = U ? Iop_Widen16Uto32x4 : Iop_Widen16Sto32x4;
6473                  break;
6474               case 3:
6475                  op = U ? Iop_ShrN64x2 : Iop_SarN64x2;
6476                  cvt = U ? Iop_QNarrowUn64Uto32Ux2 : Iop_QNarrowUn64Sto32Sx2;
6477                  cvt2 = U ? Iop_Widen32Uto64x2 : Iop_Widen32Sto64x2;
6478                  break;
6479               default:
6480                  vassert(0);
6481            }
6482            DIP("vq%sshrn.%c%u d%u, q%u, #%u\n", B ? "r" : "",
6483                U ? 'u' : 's', 8 << size, dreg, mreg, shift_imm);
6484         } else {
6485            vassert(U);
6486            switch (size) {
6487               case 1:
6488                  op = Iop_SarN16x8;
6489                  cvt = Iop_QNarrowUn16Sto8Ux8;
6490                  cvt2 = Iop_Widen8Uto16x8;
6491                  break;
6492               case 2:
6493                  op = Iop_SarN32x4;
6494                  cvt = Iop_QNarrowUn32Sto16Ux4;
6495                  cvt2 = Iop_Widen16Uto32x4;
6496                  break;
6497               case 3:
6498                  op = Iop_SarN64x2;
6499                  cvt = Iop_QNarrowUn64Sto32Ux2;
6500                  cvt2 = Iop_Widen32Uto64x2;
6501                  break;
6502               default:
6503                  vassert(0);
6504            }
6505            DIP("vq%sshrun.s%u d%u, q%u, #%u\n", B ? "r" : "",
6506                8 << size, dreg, mreg, shift_imm);
6507         }
6508         if (B) {
6509            if (shift_imm > 0) {
6510               imm = 1;
6511               switch (size) {
6512                  case 1: imm = (imm << 16) | imm; /* fall through */
6513                  case 2: imm = (imm << 32) | imm; /* fall through */
6514                  case 3: break;
6515                  case 0: default: vassert(0);
6516               }
6517               switch (size) {
6518                  case 1: add = Iop_Add16x8; break;
6519                  case 2: add = Iop_Add32x4; break;
6520                  case 3: add = Iop_Add64x2; break;
6521                  case 0: default: vassert(0);
6522               }
6523            }
6524         }
6525         reg_m = newTemp(Ity_V128);
6526         res = newTemp(Ity_V128);
6527         assign(reg_m, getQReg(mreg));
6528         if (B) {
6529            /* VQRSHRN, VQRSHRUN */
6530            assign(res, binop(add,
6531                              binop(op, mkexpr(reg_m), mkU8(shift_imm)),
6532                              binop(Iop_AndV128,
6533                                    binop(op,
6534                                          mkexpr(reg_m),
6535                                          mkU8(shift_imm - 1)),
6536                                    mkU128(imm))));
6537         } else {
6538            /* VQSHRN, VQSHRUN */
6539            assign(res, binop(op, mkexpr(reg_m), mkU8(shift_imm)));
6540         }
6541#ifndef DISABLE_QC_FLAG
6542         setFlag_QC(unop(cvt2, unop(cvt, mkexpr(res))), mkexpr(res),
6543                    True, condT);
6544#endif
6545         putDRegI64(dreg, unop(cvt, mkexpr(res)), condT);
6546         return True;
6547      case 10:
6548         /* VSHLL
6549            VMOVL ::= VSHLL #0 */
6550         if (B)
6551            return False;
6552         if (dreg & 1)
6553            return False;
6554         dreg >>= 1;
6555         shift_imm = (8 << size) - shift_imm;
6556         res = newTemp(Ity_V128);
6557         switch (size) {
6558            case 0:
6559               op = Iop_ShlN16x8;
6560               cvt = U ? Iop_Widen8Uto16x8 : Iop_Widen8Sto16x8;
6561               break;
6562            case 1:
6563               op = Iop_ShlN32x4;
6564               cvt = U ? Iop_Widen16Uto32x4 : Iop_Widen16Sto32x4;
6565               break;
6566            case 2:
6567               op = Iop_ShlN64x2;
6568               cvt = U ? Iop_Widen32Uto64x2 : Iop_Widen32Sto64x2;
6569               break;
6570            case 3:
6571               return False;
6572            default:
6573               vassert(0);
6574         }
6575         assign(res, binop(op, unop(cvt, getDRegI64(mreg)), mkU8(shift_imm)));
6576         putQReg(dreg, mkexpr(res), condT);
6577         if (shift_imm == 0) {
6578            DIP("vmovl.%c%u q%u, d%u\n", U ? 'u' : 's', 8 << size,
6579                dreg, mreg);
6580         } else {
6581            DIP("vshll.%c%u q%u, d%u, #%u\n", U ? 'u' : 's', 8 << size,
6582                dreg, mreg, shift_imm);
6583         }
6584         return True;
6585      case 14:
6586      case 15:
6587         /* VCVT floating-point <-> fixed-point */
6588         if ((theInstr >> 8) & 1) {
6589            if (U) {
6590               op = Q ? Iop_F32ToFixed32Ux4_RZ : Iop_F32ToFixed32Ux2_RZ;
6591            } else {
6592               op = Q ? Iop_F32ToFixed32Sx4_RZ : Iop_F32ToFixed32Sx2_RZ;
6593            }
6594            DIP("vcvt.%c32.f32 %c%u, %c%u, #%u\n", U ? 'u' : 's',
6595                Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg,
6596                64 - ((theInstr >> 16) & 0x3f));
6597         } else {
6598            if (U) {
6599               op = Q ? Iop_Fixed32UToF32x4_RN : Iop_Fixed32UToF32x2_RN;
6600            } else {
6601               op = Q ? Iop_Fixed32SToF32x4_RN : Iop_Fixed32SToF32x2_RN;
6602            }
6603            DIP("vcvt.f32.%c32 %c%u, %c%u, #%u\n", U ? 'u' : 's',
6604                Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg,
6605                64 - ((theInstr >> 16) & 0x3f));
6606         }
6607         if (((theInstr >> 21) & 1) == 0)
6608            return False;
6609         if (Q) {
6610            putQReg(dreg, binop(op, getQReg(mreg),
6611                     mkU8(64 - ((theInstr >> 16) & 0x3f))), condT);
6612         } else {
6613            putDRegI64(dreg, binop(op, getDRegI64(mreg),
6614                       mkU8(64 - ((theInstr >> 16) & 0x3f))), condT);
6615         }
6616         return True;
6617      default:
6618         return False;
6619
6620   }
6621   return False;
6622}
6623
6624/* A7.4.5 Two registers, miscellaneous */
6625static
6626Bool dis_neon_data_2reg_misc ( UInt theInstr, IRTemp condT )
6627{
6628   UInt A = (theInstr >> 16) & 3;
6629   UInt B = (theInstr >> 6) & 0x1f;
6630   UInt Q = (theInstr >> 6) & 1;
6631   UInt U = (theInstr >> 24) & 1;
6632   UInt size = (theInstr >> 18) & 3;
6633   UInt dreg = get_neon_d_regno(theInstr);
6634   UInt mreg = get_neon_m_regno(theInstr);
6635   UInt F = (theInstr >> 10) & 1;
6636   IRTemp arg_d;
6637   IRTemp arg_m;
6638   IRTemp res;
6639   switch (A) {
6640      case 0:
6641         if (Q) {
6642            arg_m = newTemp(Ity_V128);
6643            res = newTemp(Ity_V128);
6644            assign(arg_m, getQReg(mreg));
6645         } else {
6646            arg_m = newTemp(Ity_I64);
6647            res = newTemp(Ity_I64);
6648            assign(arg_m, getDRegI64(mreg));
6649         }
6650         switch (B >> 1) {
6651            case 0: {
6652               /* VREV64 */
6653               IROp op;
6654               switch (size) {
6655                  case 0:
6656                     op = Q ? Iop_Reverse64_8x16 : Iop_Reverse64_8x8;
6657                     break;
6658                  case 1:
6659                     op = Q ? Iop_Reverse64_16x8 : Iop_Reverse64_16x4;
6660                     break;
6661                  case 2:
6662                     op = Q ? Iop_Reverse64_32x4 : Iop_Reverse64_32x2;
6663                     break;
6664                  case 3:
6665                     return False;
6666                  default:
6667                     vassert(0);
6668               }
6669               assign(res, unop(op, mkexpr(arg_m)));
6670               DIP("vrev64.%u %c%u, %c%u\n", 8 << size,
6671                   Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg);
6672               break;
6673            }
6674            case 1: {
6675               /* VREV32 */
6676               IROp op;
6677               switch (size) {
6678                  case 0:
6679                     op = Q ? Iop_Reverse32_8x16 : Iop_Reverse32_8x8;
6680                     break;
6681                  case 1:
6682                     op = Q ? Iop_Reverse32_16x8 : Iop_Reverse32_16x4;
6683                     break;
6684                  case 2:
6685                  case 3:
6686                     return False;
6687                  default:
6688                     vassert(0);
6689               }
6690               assign(res, unop(op, mkexpr(arg_m)));
6691               DIP("vrev32.%u %c%u, %c%u\n", 8 << size,
6692                   Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg);
6693               break;
6694            }
6695            case 2: {
6696               /* VREV16 */
6697               IROp op;
6698               switch (size) {
6699                  case 0:
6700                     op = Q ? Iop_Reverse16_8x16 : Iop_Reverse16_8x8;
6701                     break;
6702                  case 1:
6703                  case 2:
6704                  case 3:
6705                     return False;
6706                  default:
6707                     vassert(0);
6708               }
6709               assign(res, unop(op, mkexpr(arg_m)));
6710               DIP("vrev16.%u %c%u, %c%u\n", 8 << size,
6711                   Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg);
6712               break;
6713            }
6714            case 3:
6715               return False;
6716            case 4:
6717            case 5: {
6718               /* VPADDL */
6719               IROp op;
6720               U = (theInstr >> 7) & 1;
6721               if (Q) {
6722                  switch (size) {
6723                     case 0: op = U ? Iop_PwAddL8Ux16 : Iop_PwAddL8Sx16; break;
6724                     case 1: op = U ? Iop_PwAddL16Ux8 : Iop_PwAddL16Sx8; break;
6725                     case 2: op = U ? Iop_PwAddL32Ux4 : Iop_PwAddL32Sx4; break;
6726                     case 3: return False;
6727                     default: vassert(0);
6728                  }
6729               } else {
6730                  switch (size) {
6731                     case 0: op = U ? Iop_PwAddL8Ux8  : Iop_PwAddL8Sx8;  break;
6732                     case 1: op = U ? Iop_PwAddL16Ux4 : Iop_PwAddL16Sx4; break;
6733                     case 2: op = U ? Iop_PwAddL32Ux2 : Iop_PwAddL32Sx2; break;
6734                     case 3: return False;
6735                     default: vassert(0);
6736                  }
6737               }
6738               assign(res, unop(op, mkexpr(arg_m)));
6739               DIP("vpaddl.%c%u %c%u, %c%u\n", U ? 'u' : 's', 8 << size,
6740                   Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg);
6741               break;
6742            }
6743            case 6:
6744            case 7:
6745               return False;
6746            case 8: {
6747               /* VCLS */
6748               IROp op;
6749               switch (size) {
6750                  case 0: op = Q ? Iop_Cls8Sx16 : Iop_Cls8Sx8; break;
6751                  case 1: op = Q ? Iop_Cls16Sx8 : Iop_Cls16Sx4; break;
6752                  case 2: op = Q ? Iop_Cls32Sx4 : Iop_Cls32Sx2; break;
6753                  case 3: return False;
6754                  default: vassert(0);
6755               }
6756               assign(res, unop(op, mkexpr(arg_m)));
6757               DIP("vcls.s%u %c%u, %c%u\n", 8 << size, Q ? 'q' : 'd', dreg,
6758                   Q ? 'q' : 'd', mreg);
6759               break;
6760            }
6761            case 9: {
6762               /* VCLZ */
6763               IROp op;
6764               switch (size) {
6765                  case 0: op = Q ? Iop_Clz8Sx16 : Iop_Clz8Sx8; break;
6766                  case 1: op = Q ? Iop_Clz16Sx8 : Iop_Clz16Sx4; break;
6767                  case 2: op = Q ? Iop_Clz32Sx4 : Iop_Clz32Sx2; break;
6768                  case 3: return False;
6769                  default: vassert(0);
6770               }
6771               assign(res, unop(op, mkexpr(arg_m)));
6772               DIP("vclz.i%u %c%u, %c%u\n", 8 << size, Q ? 'q' : 'd', dreg,
6773                   Q ? 'q' : 'd', mreg);
6774               break;
6775            }
6776            case 10:
6777               /* VCNT */
6778               assign(res, unop(Q ? Iop_Cnt8x16 : Iop_Cnt8x8, mkexpr(arg_m)));
6779               DIP("vcnt.8 %c%u, %c%u\n", Q ? 'q' : 'd', dreg, Q ? 'q' : 'd',
6780                   mreg);
6781               break;
6782            case 11:
6783               /* VMVN */
6784               if (Q)
6785                  assign(res, unop(Iop_NotV128, mkexpr(arg_m)));
6786               else
6787                  assign(res, unop(Iop_Not64, mkexpr(arg_m)));
6788               DIP("vmvn %c%u, %c%u\n", Q ? 'q' : 'd', dreg, Q ? 'q' : 'd',
6789                   mreg);
6790               break;
6791            case 12:
6792            case 13: {
6793               /* VPADAL */
6794               IROp op, add_op;
6795               U = (theInstr >> 7) & 1;
6796               if (Q) {
6797                  switch (size) {
6798                     case 0:
6799                        op = U ? Iop_PwAddL8Ux16 : Iop_PwAddL8Sx16;
6800                        add_op = Iop_Add16x8;
6801                        break;
6802                     case 1:
6803                        op = U ? Iop_PwAddL16Ux8 : Iop_PwAddL16Sx8;
6804                        add_op = Iop_Add32x4;
6805                        break;
6806                     case 2:
6807                        op = U ? Iop_PwAddL32Ux4 : Iop_PwAddL32Sx4;
6808                        add_op = Iop_Add64x2;
6809                        break;
6810                     case 3:
6811                        return False;
6812                     default:
6813                        vassert(0);
6814                  }
6815               } else {
6816                  switch (size) {
6817                     case 0:
6818                        op = U ? Iop_PwAddL8Ux8 : Iop_PwAddL8Sx8;
6819                        add_op = Iop_Add16x4;
6820                        break;
6821                     case 1:
6822                        op = U ? Iop_PwAddL16Ux4 : Iop_PwAddL16Sx4;
6823                        add_op = Iop_Add32x2;
6824                        break;
6825                     case 2:
6826                        op = U ? Iop_PwAddL32Ux2 : Iop_PwAddL32Sx2;
6827                        add_op = Iop_Add64;
6828                        break;
6829                     case 3:
6830                        return False;
6831                     default:
6832                        vassert(0);
6833                  }
6834               }
6835               if (Q) {
6836                  arg_d = newTemp(Ity_V128);
6837                  assign(arg_d, getQReg(dreg));
6838               } else {
6839                  arg_d = newTemp(Ity_I64);
6840                  assign(arg_d, getDRegI64(dreg));
6841               }
6842               assign(res, binop(add_op, unop(op, mkexpr(arg_m)),
6843                                         mkexpr(arg_d)));
6844               DIP("vpadal.%c%u %c%u, %c%u\n", U ? 'u' : 's', 8 << size,
6845                   Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg);
6846               break;
6847            }
6848            case 14: {
6849               /* VQABS */
6850               IROp op_sub, op_qsub, op_cmp;
6851               IRTemp mask, tmp;
6852               IRExpr *zero1, *zero2;
6853               IRExpr *neg, *neg2;
6854               if (Q) {
6855                  zero1 = binop(Iop_64HLtoV128, mkU64(0), mkU64(0));
6856                  zero2 = binop(Iop_64HLtoV128, mkU64(0), mkU64(0));
6857                  mask = newTemp(Ity_V128);
6858                  tmp = newTemp(Ity_V128);
6859               } else {
6860                  zero1 = mkU64(0);
6861                  zero2 = mkU64(0);
6862                  mask = newTemp(Ity_I64);
6863                  tmp = newTemp(Ity_I64);
6864               }
6865               switch (size) {
6866                  case 0:
6867                     op_sub = Q ? Iop_Sub8x16 : Iop_Sub8x8;
6868                     op_qsub = Q ? Iop_QSub8Sx16 : Iop_QSub8Sx8;
6869                     op_cmp = Q ? Iop_CmpGT8Sx16 : Iop_CmpGT8Sx8;
6870                     break;
6871                  case 1:
6872                     op_sub = Q ? Iop_Sub16x8 : Iop_Sub16x4;
6873                     op_qsub = Q ? Iop_QSub16Sx8 : Iop_QSub16Sx4;
6874                     op_cmp = Q ? Iop_CmpGT16Sx8 : Iop_CmpGT16Sx4;
6875                     break;
6876                  case 2:
6877                     op_sub = Q ? Iop_Sub32x4 : Iop_Sub32x2;
6878                     op_qsub = Q ? Iop_QSub32Sx4 : Iop_QSub32Sx2;
6879                     op_cmp = Q ? Iop_CmpGT32Sx4 : Iop_CmpGT32Sx2;
6880                     break;
6881                  case 3:
6882                     return False;
6883                  default:
6884                     vassert(0);
6885               }
6886               assign(mask, binop(op_cmp, mkexpr(arg_m), zero1));
6887               neg = binop(op_qsub, zero2, mkexpr(arg_m));
6888               neg2 = binop(op_sub, zero2, mkexpr(arg_m));
6889               assign(res, binop(Q ? Iop_OrV128 : Iop_Or64,
6890                                 binop(Q ? Iop_AndV128 : Iop_And64,
6891                                       mkexpr(mask),
6892                                       mkexpr(arg_m)),
6893                                 binop(Q ? Iop_AndV128 : Iop_And64,
6894                                       unop(Q ? Iop_NotV128 : Iop_Not64,
6895                                            mkexpr(mask)),
6896                                       neg)));
6897#ifndef DISABLE_QC_FLAG
6898               assign(tmp, binop(Q ? Iop_OrV128 : Iop_Or64,
6899                                 binop(Q ? Iop_AndV128 : Iop_And64,
6900                                       mkexpr(mask),
6901                                       mkexpr(arg_m)),
6902                                 binop(Q ? Iop_AndV128 : Iop_And64,
6903                                       unop(Q ? Iop_NotV128 : Iop_Not64,
6904                                            mkexpr(mask)),
6905                                       neg2)));
6906               setFlag_QC(mkexpr(res), mkexpr(tmp), Q, condT);
6907#endif
6908               DIP("vqabs.s%u %c%u, %c%u\n", 8 << size, Q ? 'q' : 'd', dreg,
6909                   Q ? 'q' : 'd', mreg);
6910               break;
6911            }
6912            case 15: {
6913               /* VQNEG */
6914               IROp op, op2;
6915               IRExpr *zero;
6916               if (Q) {
6917                  zero = binop(Iop_64HLtoV128, mkU64(0), mkU64(0));
6918               } else {
6919                  zero = mkU64(0);
6920               }
6921               switch (size) {
6922                  case 0:
6923                     op = Q ? Iop_QSub8Sx16 : Iop_QSub8Sx8;
6924                     op2 = Q ? Iop_Sub8x16 : Iop_Sub8x8;
6925                     break;
6926                  case 1:
6927                     op = Q ? Iop_QSub16Sx8 : Iop_QSub16Sx4;
6928                     op2 = Q ? Iop_Sub16x8 : Iop_Sub16x4;
6929                     break;
6930                  case 2:
6931                     op = Q ? Iop_QSub32Sx4 : Iop_QSub32Sx2;
6932                     op2 = Q ? Iop_Sub32x4 : Iop_Sub32x2;
6933                     break;
6934                  case 3:
6935                     return False;
6936                  default:
6937                     vassert(0);
6938               }
6939               assign(res, binop(op, zero, mkexpr(arg_m)));
6940#ifndef DISABLE_QC_FLAG
6941               setFlag_QC(mkexpr(res), binop(op2, zero, mkexpr(arg_m)),
6942                          Q, condT);
6943#endif
6944               DIP("vqneg.s%u %c%u, %c%u\n", 8 << size, Q ? 'q' : 'd', dreg,
6945                   Q ? 'q' : 'd', mreg);
6946               break;
6947            }
6948            default:
6949               vassert(0);
6950         }
6951         if (Q) {
6952            putQReg(dreg, mkexpr(res), condT);
6953         } else {
6954            putDRegI64(dreg, mkexpr(res), condT);
6955         }
6956         return True;
6957      case 1:
6958         if (Q) {
6959            arg_m = newTemp(Ity_V128);
6960            res = newTemp(Ity_V128);
6961            assign(arg_m, getQReg(mreg));
6962         } else {
6963            arg_m = newTemp(Ity_I64);
6964            res = newTemp(Ity_I64);
6965            assign(arg_m, getDRegI64(mreg));
6966         }
6967         switch ((B >> 1) & 0x7) {
6968            case 0: {
6969               /* VCGT #0 */
6970               IRExpr *zero;
6971               IROp op;
6972               if (Q) {
6973                  zero = binop(Iop_64HLtoV128, mkU64(0), mkU64(0));
6974               } else {
6975                  zero = mkU64(0);
6976               }
6977               if (F) {
6978                  switch (size) {
6979                     case 0: case 1: case 3: return False;
6980                     case 2: op = Q ? Iop_CmpGT32Fx4 : Iop_CmpGT32Fx2; break;
6981                     default: vassert(0);
6982                  }
6983               } else {
6984                  switch (size) {
6985                     case 0: op = Q ? Iop_CmpGT8Sx16 : Iop_CmpGT8Sx8; break;
6986                     case 1: op = Q ? Iop_CmpGT16Sx8 : Iop_CmpGT16Sx4; break;
6987                     case 2: op = Q ? Iop_CmpGT32Sx4 : Iop_CmpGT32Sx2; break;
6988                     case 3: return False;
6989                     default: vassert(0);
6990                  }
6991               }
6992               assign(res, binop(op, mkexpr(arg_m), zero));
6993               DIP("vcgt.%c%u %c%u, %c%u, #0\n", F ? 'f' : 's', 8 << size,
6994                   Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg);
6995               break;
6996            }
6997            case 1: {
6998               /* VCGE #0 */
6999               IROp op;
7000               IRExpr *zero;
7001               if (Q) {
7002                  zero = binop(Iop_64HLtoV128, mkU64(0), mkU64(0));
7003               } else {
7004                  zero = mkU64(0);
7005               }
7006               if (F) {
7007                  switch (size) {
7008                     case 0: case 1: case 3: return False;
7009                     case 2: op = Q ? Iop_CmpGE32Fx4 : Iop_CmpGE32Fx2; break;
7010                     default: vassert(0);
7011                  }
7012                  assign(res, binop(op, mkexpr(arg_m), zero));
7013               } else {
7014                  switch (size) {
7015                     case 0: op = Q ? Iop_CmpGT8Sx16 : Iop_CmpGT8Sx8; break;
7016                     case 1: op = Q ? Iop_CmpGT16Sx8 : Iop_CmpGT16Sx4; break;
7017                     case 2: op = Q ? Iop_CmpGT32Sx4 : Iop_CmpGT32Sx2; break;
7018                     case 3: return False;
7019                     default: vassert(0);
7020                  }
7021                  assign(res, unop(Q ? Iop_NotV128 : Iop_Not64,
7022                                   binop(op, zero, mkexpr(arg_m))));
7023               }
7024               DIP("vcge.%c%u %c%u, %c%u, #0\n", F ? 'f' : 's', 8 << size,
7025                   Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg);
7026               break;
7027            }
7028            case 2: {
7029               /* VCEQ #0 */
7030               IROp op;
7031               IRExpr *zero;
7032               if (F) {
7033                  if (Q) {
7034                     zero = binop(Iop_64HLtoV128, mkU64(0), mkU64(0));
7035                  } else {
7036                     zero = mkU64(0);
7037                  }
7038                  switch (size) {
7039                     case 0: case 1: case 3: return False;
7040                     case 2: op = Q ? Iop_CmpEQ32Fx4 : Iop_CmpEQ32Fx2; break;
7041                     default: vassert(0);
7042                  }
7043                  assign(res, binop(op, zero, mkexpr(arg_m)));
7044               } else {
7045                  switch (size) {
7046                     case 0: op = Q ? Iop_CmpNEZ8x16 : Iop_CmpNEZ8x8; break;
7047                     case 1: op = Q ? Iop_CmpNEZ16x8 : Iop_CmpNEZ16x4; break;
7048                     case 2: op = Q ? Iop_CmpNEZ32x4 : Iop_CmpNEZ32x2; break;
7049                     case 3: return False;
7050                     default: vassert(0);
7051                  }
7052                  assign(res, unop(Q ? Iop_NotV128 : Iop_Not64,
7053                                   unop(op, mkexpr(arg_m))));
7054               }
7055               DIP("vceq.%c%u %c%u, %c%u, #0\n", F ? 'f' : 'i', 8 << size,
7056                   Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg);
7057               break;
7058            }
7059            case 3: {
7060               /* VCLE #0 */
7061               IRExpr *zero;
7062               IROp op;
7063               if (Q) {
7064                  zero = binop(Iop_64HLtoV128, mkU64(0), mkU64(0));
7065               } else {
7066                  zero = mkU64(0);
7067               }
7068               if (F) {
7069                  switch (size) {
7070                     case 0: case 1: case 3: return False;
7071                     case 2: op = Q ? Iop_CmpGE32Fx4 : Iop_CmpGE32Fx2; break;
7072                     default: vassert(0);
7073                  }
7074                  assign(res, binop(op, zero, mkexpr(arg_m)));
7075               } else {
7076                  switch (size) {
7077                     case 0: op = Q ? Iop_CmpGT8Sx16 : Iop_CmpGT8Sx8; break;
7078                     case 1: op = Q ? Iop_CmpGT16Sx8 : Iop_CmpGT16Sx4; break;
7079                     case 2: op = Q ? Iop_CmpGT32Sx4 : Iop_CmpGT32Sx2; break;
7080                     case 3: return False;
7081                     default: vassert(0);
7082                  }
7083                  assign(res, unop(Q ? Iop_NotV128 : Iop_Not64,
7084                                   binop(op, mkexpr(arg_m), zero)));
7085               }
7086               DIP("vcle.%c%u %c%u, %c%u, #0\n", F ? 'f' : 's', 8 << size,
7087                   Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg);
7088               break;
7089            }
7090            case 4: {
7091               /* VCLT #0 */
7092               IROp op;
7093               IRExpr *zero;
7094               if (Q) {
7095                  zero = binop(Iop_64HLtoV128, mkU64(0), mkU64(0));
7096               } else {
7097                  zero = mkU64(0);
7098               }
7099               if (F) {
7100                  switch (size) {
7101                     case 0: case 1: case 3: return False;
7102                     case 2: op = Q ? Iop_CmpGT32Fx4 : Iop_CmpGT32Fx2; break;
7103                     default: vassert(0);
7104                  }
7105                  assign(res, binop(op, zero, mkexpr(arg_m)));
7106               } else {
7107                  switch (size) {
7108                     case 0: op = Q ? Iop_CmpGT8Sx16 : Iop_CmpGT8Sx8; break;
7109                     case 1: op = Q ? Iop_CmpGT16Sx8 : Iop_CmpGT16Sx4; break;
7110                     case 2: op = Q ? Iop_CmpGT32Sx4 : Iop_CmpGT32Sx2; break;
7111                     case 3: return False;
7112                     default: vassert(0);
7113                  }
7114                  assign(res, binop(op, zero, mkexpr(arg_m)));
7115               }
7116               DIP("vclt.%c%u %c%u, %c%u, #0\n", F ? 'f' : 's', 8 << size,
7117                   Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg);
7118               break;
7119            }
7120            case 5:
7121               return False;
7122            case 6: {
7123               /* VABS */
7124               if (!F) {
7125                  IROp op;
7126                  switch(size) {
7127                     case 0: op = Q ? Iop_Abs8x16 : Iop_Abs8x8; break;
7128                     case 1: op = Q ? Iop_Abs16x8 : Iop_Abs16x4; break;
7129                     case 2: op = Q ? Iop_Abs32x4 : Iop_Abs32x2; break;
7130                     case 3: return False;
7131                     default: vassert(0);
7132                  }
7133                  assign(res, unop(op, mkexpr(arg_m)));
7134               } else {
7135                  assign(res, unop(Q ? Iop_Abs32Fx4 : Iop_Abs32Fx2,
7136                                   mkexpr(arg_m)));
7137               }
7138               DIP("vabs.%c%u %c%u, %c%u\n",
7139                   F ? 'f' : 's', 8 << size, Q ? 'q' : 'd', dreg,
7140                   Q ? 'q' : 'd', mreg);
7141               break;
7142            }
7143            case 7: {
7144               /* VNEG */
7145               IROp op;
7146               IRExpr *zero;
7147               if (F) {
7148                  switch (size) {
7149                     case 0: case 1: case 3: return False;
7150                     case 2: op = Q ? Iop_Neg32Fx4 : Iop_Neg32Fx2; break;
7151                     default: vassert(0);
7152                  }
7153                  assign(res, unop(op, mkexpr(arg_m)));
7154               } else {
7155                  if (Q) {
7156                     zero = binop(Iop_64HLtoV128, mkU64(0), mkU64(0));
7157                  } else {
7158                     zero = mkU64(0);
7159                  }
7160                  switch (size) {
7161                     case 0: op = Q ? Iop_Sub8x16 : Iop_Sub8x8; break;
7162                     case 1: op = Q ? Iop_Sub16x8 : Iop_Sub16x4; break;
7163                     case 2: op = Q ? Iop_Sub32x4 : Iop_Sub32x2; break;
7164                     case 3: return False;
7165                     default: vassert(0);
7166                  }
7167                  assign(res, binop(op, zero, mkexpr(arg_m)));
7168               }
7169               DIP("vneg.%c%u %c%u, %c%u\n",
7170                   F ? 'f' : 's', 8 << size, Q ? 'q' : 'd', dreg,
7171                   Q ? 'q' : 'd', mreg);
7172               break;
7173            }
7174            default:
7175               vassert(0);
7176         }
7177         if (Q) {
7178            putQReg(dreg, mkexpr(res), condT);
7179         } else {
7180            putDRegI64(dreg, mkexpr(res), condT);
7181         }
7182         return True;
7183      case 2:
7184         if ((B >> 1) == 0) {
7185            /* VSWP */
7186            if (Q) {
7187               arg_m = newTemp(Ity_V128);
7188               assign(arg_m, getQReg(mreg));
7189               putQReg(mreg, getQReg(dreg), condT);
7190               putQReg(dreg, mkexpr(arg_m), condT);
7191            } else {
7192               arg_m = newTemp(Ity_I64);
7193               assign(arg_m, getDRegI64(mreg));
7194               putDRegI64(mreg, getDRegI64(dreg), condT);
7195               putDRegI64(dreg, mkexpr(arg_m), condT);
7196            }
7197            DIP("vswp %c%u, %c%u\n",
7198                Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg);
7199            return True;
7200         } else if ((B >> 1) == 1) {
7201            /* VTRN */
7202            IROp op_lo, op_hi;
7203            IRTemp res1, res2;
7204            if (Q) {
7205               arg_m = newTemp(Ity_V128);
7206               arg_d = newTemp(Ity_V128);
7207               res1 = newTemp(Ity_V128);
7208               res2 = newTemp(Ity_V128);
7209               assign(arg_m, getQReg(mreg));
7210               assign(arg_d, getQReg(dreg));
7211            } else {
7212               res1 = newTemp(Ity_I64);
7213               res2 = newTemp(Ity_I64);
7214               arg_m = newTemp(Ity_I64);
7215               arg_d = newTemp(Ity_I64);
7216               assign(arg_m, getDRegI64(mreg));
7217               assign(arg_d, getDRegI64(dreg));
7218            }
7219            if (Q) {
7220               switch (size) {
7221                  case 0:
7222                     op_lo = Iop_InterleaveOddLanes8x16;
7223                     op_hi = Iop_InterleaveEvenLanes8x16;
7224                     break;
7225                  case 1:
7226                     op_lo = Iop_InterleaveOddLanes16x8;
7227                     op_hi = Iop_InterleaveEvenLanes16x8;
7228                     break;
7229                  case 2:
7230                     op_lo = Iop_InterleaveOddLanes32x4;
7231                     op_hi = Iop_InterleaveEvenLanes32x4;
7232                     break;
7233                  case 3:
7234                     return False;
7235                  default:
7236                     vassert(0);
7237               }
7238            } else {
7239               switch (size) {
7240                  case 0:
7241                     op_lo = Iop_InterleaveOddLanes8x8;
7242                     op_hi = Iop_InterleaveEvenLanes8x8;
7243                     break;
7244                  case 1:
7245                     op_lo = Iop_InterleaveOddLanes16x4;
7246                     op_hi = Iop_InterleaveEvenLanes16x4;
7247                     break;
7248                  case 2:
7249                     op_lo = Iop_InterleaveLO32x2;
7250                     op_hi = Iop_InterleaveHI32x2;
7251                     break;
7252                  case 3:
7253                     return False;
7254                  default:
7255                     vassert(0);
7256               }
7257            }
7258            assign(res1, binop(op_lo, mkexpr(arg_m), mkexpr(arg_d)));
7259            assign(res2, binop(op_hi, mkexpr(arg_m), mkexpr(arg_d)));
7260            if (Q) {
7261               putQReg(dreg, mkexpr(res1), condT);
7262               putQReg(mreg, mkexpr(res2), condT);
7263            } else {
7264               putDRegI64(dreg, mkexpr(res1), condT);
7265               putDRegI64(mreg, mkexpr(res2), condT);
7266            }
7267            DIP("vtrn.%u %c%u, %c%u\n",
7268                8 << size, Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg);
7269            return True;
7270         } else if ((B >> 1) == 2) {
7271            /* VUZP */
7272            IROp op_lo, op_hi;
7273            IRTemp res1, res2;
7274            if (!Q && size == 2)
7275               return False;
7276            if (Q) {
7277               arg_m = newTemp(Ity_V128);
7278               arg_d = newTemp(Ity_V128);
7279               res1 = newTemp(Ity_V128);
7280               res2 = newTemp(Ity_V128);
7281               assign(arg_m, getQReg(mreg));
7282               assign(arg_d, getQReg(dreg));
7283            } else {
7284               res1 = newTemp(Ity_I64);
7285               res2 = newTemp(Ity_I64);
7286               arg_m = newTemp(Ity_I64);
7287               arg_d = newTemp(Ity_I64);
7288               assign(arg_m, getDRegI64(mreg));
7289               assign(arg_d, getDRegI64(dreg));
7290            }
7291            switch (size) {
7292               case 0:
7293                  op_lo = Q ? Iop_CatOddLanes8x16 : Iop_CatOddLanes8x8;
7294                  op_hi = Q ? Iop_CatEvenLanes8x16 : Iop_CatEvenLanes8x8;
7295                  break;
7296               case 1:
7297                  op_lo = Q ? Iop_CatOddLanes16x8 : Iop_CatOddLanes16x4;
7298                  op_hi = Q ? Iop_CatEvenLanes16x8 : Iop_CatEvenLanes16x4;
7299                  break;
7300               case 2:
7301                  op_lo = Iop_CatOddLanes32x4;
7302                  op_hi = Iop_CatEvenLanes32x4;
7303                  break;
7304               case 3:
7305                  return False;
7306               default:
7307                  vassert(0);
7308            }
7309            assign(res1, binop(op_lo, mkexpr(arg_m), mkexpr(arg_d)));
7310            assign(res2, binop(op_hi, mkexpr(arg_m), mkexpr(arg_d)));
7311            if (Q) {
7312               putQReg(dreg, mkexpr(res1), condT);
7313               putQReg(mreg, mkexpr(res2), condT);
7314            } else {
7315               putDRegI64(dreg, mkexpr(res1), condT);
7316               putDRegI64(mreg, mkexpr(res2), condT);
7317            }
7318            DIP("vuzp.%u %c%u, %c%u\n",
7319                8 << size, Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg);
7320            return True;
7321         } else if ((B >> 1) == 3) {
7322            /* VZIP */
7323            IROp op_lo, op_hi;
7324            IRTemp res1, res2;
7325            if (!Q && size == 2)
7326               return False;
7327            if (Q) {
7328               arg_m = newTemp(Ity_V128);
7329               arg_d = newTemp(Ity_V128);
7330               res1 = newTemp(Ity_V128);
7331               res2 = newTemp(Ity_V128);
7332               assign(arg_m, getQReg(mreg));
7333               assign(arg_d, getQReg(dreg));
7334            } else {
7335               res1 = newTemp(Ity_I64);
7336               res2 = newTemp(Ity_I64);
7337               arg_m = newTemp(Ity_I64);
7338               arg_d = newTemp(Ity_I64);
7339               assign(arg_m, getDRegI64(mreg));
7340               assign(arg_d, getDRegI64(dreg));
7341            }
7342            switch (size) {
7343               case 0:
7344                  op_lo = Q ? Iop_InterleaveHI8x16 : Iop_InterleaveHI8x8;
7345                  op_hi = Q ? Iop_InterleaveLO8x16 : Iop_InterleaveLO8x8;
7346                  break;
7347               case 1:
7348                  op_lo = Q ? Iop_InterleaveHI16x8 : Iop_InterleaveHI16x4;
7349                  op_hi = Q ? Iop_InterleaveLO16x8 : Iop_InterleaveLO16x4;
7350                  break;
7351               case 2:
7352                  op_lo = Iop_InterleaveHI32x4;
7353                  op_hi = Iop_InterleaveLO32x4;
7354                  break;
7355               case 3:
7356                  return False;
7357               default:
7358                  vassert(0);
7359            }
7360            assign(res1, binop(op_lo, mkexpr(arg_m), mkexpr(arg_d)));
7361            assign(res2, binop(op_hi, mkexpr(arg_m), mkexpr(arg_d)));
7362            if (Q) {
7363               putQReg(dreg, mkexpr(res1), condT);
7364               putQReg(mreg, mkexpr(res2), condT);
7365            } else {
7366               putDRegI64(dreg, mkexpr(res1), condT);
7367               putDRegI64(mreg, mkexpr(res2), condT);
7368            }
7369            DIP("vzip.%u %c%u, %c%u\n",
7370                8 << size, Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg);
7371            return True;
7372         } else if (B == 8) {
7373            /* VMOVN */
7374            IROp op;
7375            mreg >>= 1;
7376            switch (size) {
7377               case 0: op = Iop_NarrowUn16to8x8;  break;
7378               case 1: op = Iop_NarrowUn32to16x4; break;
7379               case 2: op = Iop_NarrowUn64to32x2; break;
7380               case 3: return False;
7381               default: vassert(0);
7382            }
7383            putDRegI64(dreg, unop(op, getQReg(mreg)), condT);
7384            DIP("vmovn.i%u d%u, q%u\n", 16 << size, dreg, mreg);
7385            return True;
7386         } else if (B == 9 || (B >> 1) == 5) {
7387            /* VQMOVN, VQMOVUN */
7388            IROp op, op2;
7389            IRTemp tmp;
7390            dreg = ((theInstr >> 18) & 0x10) | ((theInstr >> 12) & 0xF);
7391            mreg = ((theInstr >> 1) & 0x10) | (theInstr & 0xF);
7392            if (mreg & 1)
7393               return False;
7394            mreg >>= 1;
7395            switch (size) {
7396               case 0: op2 = Iop_NarrowUn16to8x8;  break;
7397               case 1: op2 = Iop_NarrowUn32to16x4; break;
7398               case 2: op2 = Iop_NarrowUn64to32x2; break;
7399               case 3: return False;
7400               default: vassert(0);
7401            }
7402            switch (B & 3) {
7403               case 0:
7404                  vassert(0);
7405               case 1:
7406                  switch (size) {
7407                     case 0: op = Iop_QNarrowUn16Sto8Ux8;  break;
7408                     case 1: op = Iop_QNarrowUn32Sto16Ux4; break;
7409                     case 2: op = Iop_QNarrowUn64Sto32Ux2; break;
7410                     case 3: return False;
7411                     default: vassert(0);
7412                  }
7413                  DIP("vqmovun.s%u d%u, q%u\n", 16 << size, dreg, mreg);
7414                  break;
7415               case 2:
7416                  switch (size) {
7417                     case 0: op = Iop_QNarrowUn16Sto8Sx8;  break;
7418                     case 1: op = Iop_QNarrowUn32Sto16Sx4; break;
7419                     case 2: op = Iop_QNarrowUn64Sto32Sx2; break;
7420                     case 3: return False;
7421                     default: vassert(0);
7422                  }
7423                  DIP("vqmovn.s%u d%u, q%u\n", 16 << size, dreg, mreg);
7424                  break;
7425               case 3:
7426                  switch (size) {
7427                     case 0: op = Iop_QNarrowUn16Uto8Ux8;  break;
7428                     case 1: op = Iop_QNarrowUn32Uto16Ux4; break;
7429                     case 2: op = Iop_QNarrowUn64Uto32Ux2; break;
7430                     case 3: return False;
7431                     default: vassert(0);
7432                  }
7433                  DIP("vqmovn.u%u d%u, q%u\n", 16 << size, dreg, mreg);
7434                  break;
7435               default:
7436                  vassert(0);
7437            }
7438            res = newTemp(Ity_I64);
7439            tmp = newTemp(Ity_I64);
7440            assign(res, unop(op, getQReg(mreg)));
7441#ifndef DISABLE_QC_FLAG
7442            assign(tmp, unop(op2, getQReg(mreg)));
7443            setFlag_QC(mkexpr(res), mkexpr(tmp), False, condT);
7444#endif
7445            putDRegI64(dreg, mkexpr(res), condT);
7446            return True;
7447         } else if (B == 12) {
7448            /* VSHLL (maximum shift) */
7449            IROp op, cvt;
7450            UInt shift_imm;
7451            if (Q)
7452               return False;
7453            if (dreg & 1)
7454               return False;
7455            dreg >>= 1;
7456            shift_imm = 8 << size;
7457            res = newTemp(Ity_V128);
7458            switch (size) {
7459               case 0: op = Iop_ShlN16x8; cvt = Iop_Widen8Uto16x8;  break;
7460               case 1: op = Iop_ShlN32x4; cvt = Iop_Widen16Uto32x4; break;
7461               case 2: op = Iop_ShlN64x2; cvt = Iop_Widen32Uto64x2; break;
7462               case 3: return False;
7463               default: vassert(0);
7464            }
7465            assign(res, binop(op, unop(cvt, getDRegI64(mreg)),
7466                                  mkU8(shift_imm)));
7467            putQReg(dreg, mkexpr(res), condT);
7468            DIP("vshll.i%u q%u, d%u, #%u\n", 8 << size, dreg, mreg, 8 << size);
7469            return True;
7470         } else if ((B >> 3) == 3 && (B & 3) == 0) {
7471            /* VCVT (half<->single) */
7472            /* Half-precision extensions are needed to run this */
7473            vassert(0); // ATC
7474            if (((theInstr >> 18) & 3) != 1)
7475               return False;
7476            if ((theInstr >> 8) & 1) {
7477               if (dreg & 1)
7478                  return False;
7479               dreg >>= 1;
7480               putQReg(dreg, unop(Iop_F16toF32x4, getDRegI64(mreg)),
7481                     condT);
7482               DIP("vcvt.f32.f16 q%u, d%u\n", dreg, mreg);
7483            } else {
7484               if (mreg & 1)
7485                  return False;
7486               mreg >>= 1;
7487               putDRegI64(dreg, unop(Iop_F32toF16x4, getQReg(mreg)),
7488                                condT);
7489               DIP("vcvt.f16.f32 d%u, q%u\n", dreg, mreg);
7490            }
7491            return True;
7492         } else {
7493            return False;
7494         }
7495         vassert(0);
7496         return True;
7497      case 3:
7498         if (((B >> 1) & BITS4(1,1,0,1)) == BITS4(1,0,0,0)) {
7499            /* VRECPE */
7500            IROp op;
7501            F = (theInstr >> 8) & 1;
7502            if (size != 2)
7503               return False;
7504            if (Q) {
7505               op = F ? Iop_Recip32Fx4 : Iop_Recip32x4;
7506               putQReg(dreg, unop(op, getQReg(mreg)), condT);
7507               DIP("vrecpe.%c32 q%u, q%u\n", F ? 'f' : 'u', dreg, mreg);
7508            } else {
7509               op = F ? Iop_Recip32Fx2 : Iop_Recip32x2;
7510               putDRegI64(dreg, unop(op, getDRegI64(mreg)), condT);
7511               DIP("vrecpe.%c32 d%u, d%u\n", F ? 'f' : 'u', dreg, mreg);
7512            }
7513            return True;
7514         } else if (((B >> 1) & BITS4(1,1,0,1)) == BITS4(1,0,0,1)) {
7515            /* VRSQRTE */
7516            IROp op;
7517            F = (B >> 2) & 1;
7518            if (size != 2)
7519               return False;
7520            if (F) {
7521               /* fp */
7522               op = Q ? Iop_Rsqrte32Fx4 : Iop_Rsqrte32Fx2;
7523            } else {
7524               /* unsigned int */
7525               op = Q ? Iop_Rsqrte32x4 : Iop_Rsqrte32x2;
7526            }
7527            if (Q) {
7528               putQReg(dreg, unop(op, getQReg(mreg)), condT);
7529               DIP("vrsqrte.%c32 q%u, q%u\n", F ? 'f' : 'u', dreg, mreg);
7530            } else {
7531               putDRegI64(dreg, unop(op, getDRegI64(mreg)), condT);
7532               DIP("vrsqrte.%c32 d%u, d%u\n", F ? 'f' : 'u', dreg, mreg);
7533            }
7534            return True;
7535         } else if ((B >> 3) == 3) {
7536            /* VCVT (fp<->integer) */
7537            IROp op;
7538            if (size != 2)
7539               return False;
7540            switch ((B >> 1) & 3) {
7541               case 0:
7542                  op = Q ? Iop_I32StoFx4 : Iop_I32StoFx2;
7543                  DIP("vcvt.f32.s32 %c%u, %c%u\n",
7544                      Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg);
7545                  break;
7546               case 1:
7547                  op = Q ? Iop_I32UtoFx4 : Iop_I32UtoFx2;
7548                  DIP("vcvt.f32.u32 %c%u, %c%u\n",
7549                      Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg);
7550                  break;
7551               case 2:
7552                  op = Q ? Iop_FtoI32Sx4_RZ : Iop_FtoI32Sx2_RZ;
7553                  DIP("vcvt.s32.f32 %c%u, %c%u\n",
7554                      Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg);
7555                  break;
7556               case 3:
7557                  op = Q ? Iop_FtoI32Ux4_RZ : Iop_FtoI32Ux2_RZ;
7558                  DIP("vcvt.u32.f32 %c%u, %c%u\n",
7559                      Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg);
7560                  break;
7561               default:
7562                  vassert(0);
7563            }
7564            if (Q) {
7565               putQReg(dreg, unop(op, getQReg(mreg)), condT);
7566            } else {
7567               putDRegI64(dreg, unop(op, getDRegI64(mreg)), condT);
7568            }
7569            return True;
7570         } else {
7571            return False;
7572         }
7573         vassert(0);
7574         return True;
7575      default:
7576         vassert(0);
7577   }
7578   return False;
7579}
7580
7581/* A7.4.6 One register and a modified immediate value */
7582static
7583void ppNeonImm(UInt imm, UInt cmode, UInt op)
7584{
7585   int i;
7586   switch (cmode) {
7587      case 0: case 1: case 8: case 9:
7588         vex_printf("0x%x", imm);
7589         break;
7590      case 2: case 3: case 10: case 11:
7591         vex_printf("0x%x00", imm);
7592         break;
7593      case 4: case 5:
7594         vex_printf("0x%x0000", imm);
7595         break;
7596      case 6: case 7:
7597         vex_printf("0x%x000000", imm);
7598         break;
7599      case 12:
7600         vex_printf("0x%xff", imm);
7601         break;
7602      case 13:
7603         vex_printf("0x%xffff", imm);
7604         break;
7605      case 14:
7606         if (op) {
7607            vex_printf("0x");
7608            for (i = 7; i >= 0; i--)
7609               vex_printf("%s", (imm & (1 << i)) ? "ff" : "00");
7610         } else {
7611            vex_printf("0x%x", imm);
7612         }
7613         break;
7614      case 15:
7615         vex_printf("0x%x", imm);
7616         break;
7617   }
7618}
7619
7620static
7621const char *ppNeonImmType(UInt cmode, UInt op)
7622{
7623   switch (cmode) {
7624      case 0 ... 7:
7625      case 12: case 13:
7626         return "i32";
7627      case 8 ... 11:
7628         return "i16";
7629      case 14:
7630         if (op)
7631            return "i64";
7632         else
7633            return "i8";
7634      case 15:
7635         if (op)
7636            vassert(0);
7637         else
7638            return "f32";
7639      default:
7640         vassert(0);
7641   }
7642}
7643
7644static
7645void DIPimm(UInt imm, UInt cmode, UInt op,
7646            const char *instr, UInt Q, UInt dreg)
7647{
7648   if (vex_traceflags & VEX_TRACE_FE) {
7649      vex_printf("%s.%s %c%u, #", instr,
7650                 ppNeonImmType(cmode, op), Q ? 'q' : 'd', dreg);
7651      ppNeonImm(imm, cmode, op);
7652      vex_printf("\n");
7653   }
7654}
7655
7656static
7657Bool dis_neon_data_1reg_and_imm ( UInt theInstr, IRTemp condT )
7658{
7659   UInt dreg = get_neon_d_regno(theInstr);
7660   ULong imm_raw = ((theInstr >> 17) & 0x80) | ((theInstr >> 12) & 0x70) |
7661                  (theInstr & 0xf);
7662   ULong imm_raw_pp = imm_raw;
7663   UInt cmode = (theInstr >> 8) & 0xf;
7664   UInt op_bit = (theInstr >> 5) & 1;
7665   ULong imm = 0;
7666   UInt Q = (theInstr >> 6) & 1;
7667   int i, j;
7668   UInt tmp;
7669   IRExpr *imm_val;
7670   IRExpr *expr;
7671   IRTemp tmp_var;
7672   switch(cmode) {
7673      case 7: case 6:
7674         imm_raw = imm_raw << 8;
7675         /* fallthrough */
7676      case 5: case 4:
7677         imm_raw = imm_raw << 8;
7678         /* fallthrough */
7679      case 3: case 2:
7680         imm_raw = imm_raw << 8;
7681         /* fallthrough */
7682      case 0: case 1:
7683         imm = (imm_raw << 32) | imm_raw;
7684         break;
7685      case 11: case 10:
7686         imm_raw = imm_raw << 8;
7687         /* fallthrough */
7688      case 9: case 8:
7689         imm_raw = (imm_raw << 16) | imm_raw;
7690         imm = (imm_raw << 32) | imm_raw;
7691         break;
7692      case 13:
7693         imm_raw = (imm_raw << 8) | 0xff;
7694         /* fallthrough */
7695      case 12:
7696         imm_raw = (imm_raw << 8) | 0xff;
7697         imm = (imm_raw << 32) | imm_raw;
7698         break;
7699      case 14:
7700         if (! op_bit) {
7701            for(i = 0; i < 8; i++) {
7702               imm = (imm << 8) | imm_raw;
7703            }
7704         } else {
7705            for(i = 7; i >= 0; i--) {
7706               tmp = 0;
7707               for(j = 0; j < 8; j++) {
7708                  tmp = (tmp << 1) | ((imm_raw >> i) & 1);
7709               }
7710               imm = (imm << 8) | tmp;
7711            }
7712         }
7713         break;
7714      case 15:
7715         imm = (imm_raw & 0x80) << 5;
7716         imm |= ((~imm_raw & 0x40) << 5);
7717         for(i = 1; i <= 4; i++)
7718            imm |= (imm_raw & 0x40) << i;
7719         imm |= (imm_raw & 0x7f);
7720         imm = imm << 19;
7721         imm = (imm << 32) | imm;
7722         break;
7723      default:
7724         return False;
7725   }
7726   if (Q) {
7727      imm_val = binop(Iop_64HLtoV128, mkU64(imm), mkU64(imm));
7728   } else {
7729      imm_val = mkU64(imm);
7730   }
7731   if (((op_bit == 0) &&
7732      (((cmode & 9) == 0) || ((cmode & 13) == 8) || ((cmode & 12) == 12))) ||
7733      ((op_bit == 1) && (cmode == 14))) {
7734      /* VMOV (immediate) */
7735      if (Q) {
7736         putQReg(dreg, imm_val, condT);
7737      } else {
7738         putDRegI64(dreg, imm_val, condT);
7739      }
7740      DIPimm(imm_raw_pp, cmode, op_bit, "vmov", Q, dreg);
7741      return True;
7742   }
7743   if ((op_bit == 1) &&
7744      (((cmode & 9) == 0) || ((cmode & 13) == 8) || ((cmode & 14) == 12))) {
7745      /* VMVN (immediate) */
7746      if (Q) {
7747         putQReg(dreg, unop(Iop_NotV128, imm_val), condT);
7748      } else {
7749         putDRegI64(dreg, unop(Iop_Not64, imm_val), condT);
7750      }
7751      DIPimm(imm_raw_pp, cmode, op_bit, "vmvn", Q, dreg);
7752      return True;
7753   }
7754   if (Q) {
7755      tmp_var = newTemp(Ity_V128);
7756      assign(tmp_var, getQReg(dreg));
7757   } else {
7758      tmp_var = newTemp(Ity_I64);
7759      assign(tmp_var, getDRegI64(dreg));
7760   }
7761   if ((op_bit == 0) && (((cmode & 9) == 1) || ((cmode & 13) == 9))) {
7762      /* VORR (immediate) */
7763      if (Q)
7764         expr = binop(Iop_OrV128, mkexpr(tmp_var), imm_val);
7765      else
7766         expr = binop(Iop_Or64, mkexpr(tmp_var), imm_val);
7767      DIPimm(imm_raw_pp, cmode, op_bit, "vorr", Q, dreg);
7768   } else if ((op_bit == 1) && (((cmode & 9) == 1) || ((cmode & 13) == 9))) {
7769      /* VBIC (immediate) */
7770      if (Q)
7771         expr = binop(Iop_AndV128, mkexpr(tmp_var),
7772                                   unop(Iop_NotV128, imm_val));
7773      else
7774         expr = binop(Iop_And64, mkexpr(tmp_var), unop(Iop_Not64, imm_val));
7775      DIPimm(imm_raw_pp, cmode, op_bit, "vbic", Q, dreg);
7776   } else {
7777      return False;
7778   }
7779   if (Q)
7780      putQReg(dreg, expr, condT);
7781   else
7782      putDRegI64(dreg, expr, condT);
7783   return True;
7784}
7785
7786/* A7.4 Advanced SIMD data-processing instructions */
7787static
7788Bool dis_neon_data_processing ( UInt theInstr, IRTemp condT )
7789{
7790   UInt A = (theInstr >> 19) & 0x1F;
7791   UInt B = (theInstr >>  8) & 0xF;
7792   UInt C = (theInstr >>  4) & 0xF;
7793   UInt U = (theInstr >> 24) & 0x1;
7794
7795   if (! (A & 0x10)) {
7796      return dis_neon_data_3same(theInstr, condT);
7797   }
7798   if (((A & 0x17) == 0x10) && ((C & 0x9) == 0x1)) {
7799      return dis_neon_data_1reg_and_imm(theInstr, condT);
7800   }
7801   if ((C & 1) == 1) {
7802      return dis_neon_data_2reg_and_shift(theInstr, condT);
7803   }
7804   if (((C & 5) == 0) && (((A & 0x14) == 0x10) || ((A & 0x16) == 0x14))) {
7805      return dis_neon_data_3diff(theInstr, condT);
7806   }
7807   if (((C & 5) == 4) && (((A & 0x14) == 0x10) || ((A & 0x16) == 0x14))) {
7808      return dis_neon_data_2reg_and_scalar(theInstr, condT);
7809   }
7810   if ((A & 0x16) == 0x16) {
7811      if ((U == 0) && ((C & 1) == 0)) {
7812         return dis_neon_vext(theInstr, condT);
7813      }
7814      if ((U != 1) || ((C & 1) == 1))
7815         return False;
7816      if ((B & 8) == 0) {
7817         return dis_neon_data_2reg_misc(theInstr, condT);
7818      }
7819      if ((B & 12) == 8) {
7820         return dis_neon_vtb(theInstr, condT);
7821      }
7822      if ((B == 12) && ((C & 9) == 0)) {
7823         return dis_neon_vdup(theInstr, condT);
7824      }
7825   }
7826   return False;
7827}
7828
7829
7830/*------------------------------------------------------------*/
7831/*--- NEON loads and stores                                ---*/
7832/*------------------------------------------------------------*/
7833
7834/* For NEON memory operations, we use the standard scheme to handle
7835   conditionalisation: generate a jump around the instruction if the
7836   condition is false.  That's only necessary in Thumb mode, however,
7837   since in ARM mode NEON instructions are unconditional. */
7838
7839/* A helper function for what follows.  It assumes we already went
7840   uncond as per comments at the top of this section. */
7841static
7842void mk_neon_elem_load_to_one_lane( UInt rD, UInt inc, UInt index,
7843                                    UInt N, UInt size, IRTemp addr )
7844{
7845   UInt i;
7846   switch (size) {
7847      case 0:
7848         putDRegI64(rD, triop(Iop_SetElem8x8, getDRegI64(rD), mkU8(index),
7849                    loadLE(Ity_I8, mkexpr(addr))), IRTemp_INVALID);
7850         break;
7851      case 1:
7852         putDRegI64(rD, triop(Iop_SetElem16x4, getDRegI64(rD), mkU8(index),
7853                    loadLE(Ity_I16, mkexpr(addr))), IRTemp_INVALID);
7854         break;
7855      case 2:
7856         putDRegI64(rD, triop(Iop_SetElem32x2, getDRegI64(rD), mkU8(index),
7857                    loadLE(Ity_I32, mkexpr(addr))), IRTemp_INVALID);
7858         break;
7859      default:
7860         vassert(0);
7861   }
7862   for (i = 1; i <= N; i++) {
7863      switch (size) {
7864         case 0:
7865            putDRegI64(rD + i * inc,
7866                       triop(Iop_SetElem8x8,
7867                             getDRegI64(rD + i * inc),
7868                             mkU8(index),
7869                             loadLE(Ity_I8, binop(Iop_Add32,
7870                                                  mkexpr(addr),
7871                                                  mkU32(i * 1)))),
7872                       IRTemp_INVALID);
7873            break;
7874         case 1:
7875            putDRegI64(rD + i * inc,
7876                       triop(Iop_SetElem16x4,
7877                             getDRegI64(rD + i * inc),
7878                             mkU8(index),
7879                             loadLE(Ity_I16, binop(Iop_Add32,
7880                                                   mkexpr(addr),
7881                                                   mkU32(i * 2)))),
7882                       IRTemp_INVALID);
7883            break;
7884         case 2:
7885            putDRegI64(rD + i * inc,
7886                       triop(Iop_SetElem32x2,
7887                             getDRegI64(rD + i * inc),
7888                             mkU8(index),
7889                             loadLE(Ity_I32, binop(Iop_Add32,
7890                                                   mkexpr(addr),
7891                                                   mkU32(i * 4)))),
7892                       IRTemp_INVALID);
7893            break;
7894         default:
7895            vassert(0);
7896      }
7897   }
7898}
7899
7900/* A(nother) helper function for what follows.  It assumes we already
7901   went uncond as per comments at the top of this section. */
7902static
7903void mk_neon_elem_store_from_one_lane( UInt rD, UInt inc, UInt index,
7904                                       UInt N, UInt size, IRTemp addr )
7905{
7906   UInt i;
7907   switch (size) {
7908      case 0:
7909         storeLE(mkexpr(addr),
7910                 binop(Iop_GetElem8x8, getDRegI64(rD), mkU8(index)));
7911         break;
7912      case 1:
7913         storeLE(mkexpr(addr),
7914                 binop(Iop_GetElem16x4, getDRegI64(rD), mkU8(index)));
7915         break;
7916      case 2:
7917         storeLE(mkexpr(addr),
7918                 binop(Iop_GetElem32x2, getDRegI64(rD), mkU8(index)));
7919         break;
7920      default:
7921         vassert(0);
7922   }
7923   for (i = 1; i <= N; i++) {
7924      switch (size) {
7925         case 0:
7926            storeLE(binop(Iop_Add32, mkexpr(addr), mkU32(i * 1)),
7927                    binop(Iop_GetElem8x8, getDRegI64(rD + i * inc),
7928                                          mkU8(index)));
7929            break;
7930         case 1:
7931            storeLE(binop(Iop_Add32, mkexpr(addr), mkU32(i * 2)),
7932                    binop(Iop_GetElem16x4, getDRegI64(rD + i * inc),
7933                                           mkU8(index)));
7934            break;
7935         case 2:
7936            storeLE(binop(Iop_Add32, mkexpr(addr), mkU32(i * 4)),
7937                    binop(Iop_GetElem32x2, getDRegI64(rD + i * inc),
7938                                           mkU8(index)));
7939            break;
7940         default:
7941            vassert(0);
7942      }
7943   }
7944}
7945
7946/* A7.7 Advanced SIMD element or structure load/store instructions */
7947static
7948Bool dis_neon_load_or_store ( UInt theInstr,
7949                              Bool isT, IRTemp condT )
7950{
7951#  define INSN(_bMax,_bMin)  SLICE_UInt(theInstr, (_bMax), (_bMin))
7952   UInt bA = INSN(23,23);
7953   UInt fB = INSN(11,8);
7954   UInt bL = INSN(21,21);
7955   UInt rD = (INSN(22,22) << 4) | INSN(15,12);
7956   UInt rN = INSN(19,16);
7957   UInt rM = INSN(3,0);
7958   UInt N, size, i, j;
7959   UInt inc;
7960   UInt regs = 1;
7961
7962   if (isT) {
7963      vassert(condT != IRTemp_INVALID);
7964   } else {
7965      vassert(condT == IRTemp_INVALID);
7966   }
7967   /* So now, if condT is not IRTemp_INVALID, we know we're
7968      dealing with Thumb code. */
7969
7970   if (INSN(20,20) != 0)
7971      return False;
7972
7973   IRTemp initialRn = newTemp(Ity_I32);
7974   assign(initialRn, isT ? getIRegT(rN) : getIRegA(rN));
7975
7976   IRTemp initialRm = newTemp(Ity_I32);
7977   assign(initialRm, isT ? getIRegT(rM) : getIRegA(rM));
7978
7979   /* There are 3 cases:
7980      (1) VSTn / VLDn (n-element structure from/to one lane)
7981      (2) VLDn (single element to all lanes)
7982      (3) VSTn / VLDn (multiple n-element structures)
7983   */
7984   if (bA) {
7985      N = fB & 3;
7986      if ((fB >> 2) < 3) {
7987         /* ------------ Case (1) ------------
7988            VSTn / VLDn (n-element structure from/to one lane) */
7989
7990         size = fB >> 2;
7991
7992         switch (size) {
7993            case 0: i = INSN(7,5); inc = 1; break;
7994            case 1: i = INSN(7,6); inc = INSN(5,5) ? 2 : 1; break;
7995            case 2: i = INSN(7,7); inc = INSN(6,6) ? 2 : 1; break;
7996            case 3: return False;
7997            default: vassert(0);
7998         }
7999
8000         IRTemp addr = newTemp(Ity_I32);
8001         assign(addr, mkexpr(initialRn));
8002
8003         // go uncond
8004         if (condT != IRTemp_INVALID)
8005            mk_skip_over_T32_if_cond_is_false(condT);
8006         // now uncond
8007
8008         if (bL)
8009            mk_neon_elem_load_to_one_lane(rD, inc, i, N, size, addr);
8010         else
8011            mk_neon_elem_store_from_one_lane(rD, inc, i, N, size, addr);
8012         DIP("v%s%u.%u {", bL ? "ld" : "st", N + 1, 8 << size);
8013         for (j = 0; j <= N; j++) {
8014            if (j)
8015               DIP(", ");
8016            DIP("d%u[%u]", rD + j * inc, i);
8017         }
8018         DIP("}, [r%u]", rN);
8019         if (rM != 13 && rM != 15) {
8020            DIP(", r%u\n", rM);
8021         } else {
8022            DIP("%s\n", (rM != 15) ? "!" : "");
8023         }
8024      } else {
8025         /* ------------ Case (2) ------------
8026            VLDn (single element to all lanes) */
8027         UInt r;
8028         if (bL == 0)
8029            return False;
8030
8031         inc = INSN(5,5) + 1;
8032         size = INSN(7,6);
8033
8034         /* size == 3 and size == 2 cases differ in alignment constraints */
8035         if (size == 3 && N == 3 && INSN(4,4) == 1)
8036            size = 2;
8037
8038         if (size == 0 && N == 0 && INSN(4,4) == 1)
8039            return False;
8040         if (N == 2 && INSN(4,4) == 1)
8041            return False;
8042         if (size == 3)
8043            return False;
8044
8045         // go uncond
8046         if (condT != IRTemp_INVALID)
8047            mk_skip_over_T32_if_cond_is_false(condT);
8048         // now uncond
8049
8050         IRTemp addr = newTemp(Ity_I32);
8051         assign(addr, mkexpr(initialRn));
8052
8053         if (N == 0 && INSN(5,5))
8054            regs = 2;
8055
8056         for (r = 0; r < regs; r++) {
8057            switch (size) {
8058               case 0:
8059                  putDRegI64(rD + r, unop(Iop_Dup8x8,
8060                                          loadLE(Ity_I8, mkexpr(addr))),
8061                             IRTemp_INVALID);
8062                  break;
8063               case 1:
8064                  putDRegI64(rD + r, unop(Iop_Dup16x4,
8065                                          loadLE(Ity_I16, mkexpr(addr))),
8066                             IRTemp_INVALID);
8067                  break;
8068               case 2:
8069                  putDRegI64(rD + r, unop(Iop_Dup32x2,
8070                                          loadLE(Ity_I32, mkexpr(addr))),
8071                             IRTemp_INVALID);
8072                  break;
8073               default:
8074                  vassert(0);
8075            }
8076            for (i = 1; i <= N; i++) {
8077               switch (size) {
8078                  case 0:
8079                     putDRegI64(rD + r + i * inc,
8080                                unop(Iop_Dup8x8,
8081                                     loadLE(Ity_I8, binop(Iop_Add32,
8082                                                          mkexpr(addr),
8083                                                          mkU32(i * 1)))),
8084                                IRTemp_INVALID);
8085                     break;
8086                  case 1:
8087                     putDRegI64(rD + r + i * inc,
8088                                unop(Iop_Dup16x4,
8089                                     loadLE(Ity_I16, binop(Iop_Add32,
8090                                                           mkexpr(addr),
8091                                                           mkU32(i * 2)))),
8092                                IRTemp_INVALID);
8093                     break;
8094                  case 2:
8095                     putDRegI64(rD + r + i * inc,
8096                                unop(Iop_Dup32x2,
8097                                     loadLE(Ity_I32, binop(Iop_Add32,
8098                                                           mkexpr(addr),
8099                                                           mkU32(i * 4)))),
8100                                IRTemp_INVALID);
8101                     break;
8102                  default:
8103                     vassert(0);
8104               }
8105            }
8106         }
8107         DIP("vld%u.%u {", N + 1, 8 << size);
8108         for (r = 0; r < regs; r++) {
8109            for (i = 0; i <= N; i++) {
8110               if (i || r)
8111                  DIP(", ");
8112               DIP("d%u[]", rD + r + i * inc);
8113            }
8114         }
8115         DIP("}, [r%u]", rN);
8116         if (rM != 13 && rM != 15) {
8117            DIP(", r%u\n", rM);
8118         } else {
8119            DIP("%s\n", (rM != 15) ? "!" : "");
8120         }
8121      }
8122      /* Writeback.  We're uncond here, so no condT-ing. */
8123      if (rM != 15) {
8124         if (rM == 13) {
8125            IRExpr* e = binop(Iop_Add32,
8126                              mkexpr(initialRn),
8127                              mkU32((1 << size) * (N + 1)));
8128            if (isT)
8129               putIRegT(rN, e, IRTemp_INVALID);
8130            else
8131               putIRegA(rN, e, IRTemp_INVALID, Ijk_Boring);
8132         } else {
8133            IRExpr* e = binop(Iop_Add32,
8134                              mkexpr(initialRn),
8135                              mkexpr(initialRm));
8136            if (isT)
8137               putIRegT(rN, e, IRTemp_INVALID);
8138            else
8139               putIRegA(rN, e, IRTemp_INVALID, Ijk_Boring);
8140         }
8141      }
8142      return True;
8143   } else {
8144      /* ------------ Case (3) ------------
8145         VSTn / VLDn (multiple n-element structures) */
8146      IRTemp tmp;
8147      UInt r, elems;
8148      if (fB == BITS4(0,0,1,0) || fB == BITS4(0,1,1,0)
8149          || fB == BITS4(0,1,1,1) || fB == BITS4(1,0,1,0)) {
8150         N = 0;
8151      } else if (fB == BITS4(0,0,1,1) || fB == BITS4(1,0,0,0)
8152                 || fB == BITS4(1,0,0,1)) {
8153         N = 1;
8154      } else if (fB == BITS4(0,1,0,0) || fB == BITS4(0,1,0,1)) {
8155         N = 2;
8156      } else if (fB == BITS4(0,0,0,0) || fB == BITS4(0,0,0,1)) {
8157         N = 3;
8158      } else {
8159         return False;
8160      }
8161      inc = (fB & 1) + 1;
8162      if (N == 1 && fB == BITS4(0,0,1,1)) {
8163         regs = 2;
8164      } else if (N == 0) {
8165         if (fB == BITS4(1,0,1,0)) {
8166            regs = 2;
8167         } else if (fB == BITS4(0,1,1,0)) {
8168            regs = 3;
8169         } else if (fB == BITS4(0,0,1,0)) {
8170            regs = 4;
8171         }
8172      }
8173
8174      size = INSN(7,6);
8175      if (N == 0 && size == 3)
8176         size = 2;
8177      if (size == 3)
8178         return False;
8179
8180      elems = 8 / (1 << size);
8181
8182      // go uncond
8183      if (condT != IRTemp_INVALID)
8184         mk_skip_over_T32_if_cond_is_false(condT);
8185      // now uncond
8186
8187      IRTemp addr = newTemp(Ity_I32);
8188      assign(addr, mkexpr(initialRn));
8189
8190      for (r = 0; r < regs; r++) {
8191         for (i = 0; i < elems; i++) {
8192            if (bL)
8193               mk_neon_elem_load_to_one_lane(rD + r, inc, i, N, size, addr);
8194            else
8195               mk_neon_elem_store_from_one_lane(rD + r, inc, i, N, size, addr);
8196            tmp = newTemp(Ity_I32);
8197            assign(tmp, binop(Iop_Add32, mkexpr(addr),
8198                                         mkU32((1 << size) * (N + 1))));
8199            addr = tmp;
8200         }
8201      }
8202      /* Writeback */
8203      if (rM != 15) {
8204         if (rM == 13) {
8205            IRExpr* e = binop(Iop_Add32,
8206                              mkexpr(initialRn),
8207                              mkU32(8 * (N + 1) * regs));
8208            if (isT)
8209               putIRegT(rN, e, IRTemp_INVALID);
8210            else
8211               putIRegA(rN, e, IRTemp_INVALID, Ijk_Boring);
8212         } else {
8213            IRExpr* e = binop(Iop_Add32,
8214                              mkexpr(initialRn),
8215                              mkexpr(initialRm));
8216            if (isT)
8217               putIRegT(rN, e, IRTemp_INVALID);
8218            else
8219               putIRegA(rN, e, IRTemp_INVALID, Ijk_Boring);
8220         }
8221      }
8222      DIP("v%s%u.%u {", bL ? "ld" : "st", N + 1, 8 << INSN(7,6));
8223      if ((inc == 1 && regs * (N + 1) > 1)
8224          || (inc == 2 && regs > 1 && N > 0)) {
8225         DIP("d%u-d%u", rD, rD + regs * (N + 1) - 1);
8226      } else {
8227         for (r = 0; r < regs; r++) {
8228            for (i = 0; i <= N; i++) {
8229               if (i || r)
8230                  DIP(", ");
8231               DIP("d%u", rD + r + i * inc);
8232            }
8233         }
8234      }
8235      DIP("}, [r%u]", rN);
8236      if (rM != 13 && rM != 15) {
8237         DIP(", r%u\n", rM);
8238      } else {
8239         DIP("%s\n", (rM != 15) ? "!" : "");
8240      }
8241      return True;
8242   }
8243#  undef INSN
8244}
8245
8246
8247/*------------------------------------------------------------*/
8248/*--- NEON, top level control                              ---*/
8249/*------------------------------------------------------------*/
8250
8251/* Both ARM and Thumb */
8252
8253/* Translate a NEON instruction.    If successful, returns
8254   True and *dres may or may not be updated.  If failure, returns
8255   False and doesn't change *dres nor create any IR.
8256
8257   The Thumb and ARM encodings are similar for the 24 bottom bits, but
8258   the top 8 bits are slightly different.  In both cases, the caller
8259   must pass the entire 32 bits.  Callers may pass any instruction;
8260   this ignores non-NEON ones.
8261
8262   Caller must supply an IRTemp 'condT' holding the gating condition,
8263   or IRTemp_INVALID indicating the insn is always executed.  In ARM
8264   code, this must always be IRTemp_INVALID because NEON insns are
8265   unconditional for ARM.
8266
8267   Finally, the caller must indicate whether this occurs in ARM or in
8268   Thumb code.
8269*/
8270static Bool decode_NEON_instruction (
8271               /*MOD*/DisResult* dres,
8272               UInt              insn32,
8273               IRTemp            condT,
8274               Bool              isT
8275            )
8276{
8277#  define INSN(_bMax,_bMin)  SLICE_UInt(insn32, (_bMax), (_bMin))
8278
8279   /* There are two kinds of instruction to deal with: load/store and
8280      data processing.  In each case, in ARM mode we merely identify
8281      the kind, and pass it on to the relevant sub-handler.  In Thumb
8282      mode we identify the kind, swizzle the bits around to make it
8283      have the same encoding as in ARM, and hand it on to the
8284      sub-handler.
8285   */
8286
8287   /* In ARM mode, NEON instructions can't be conditional. */
8288   if (!isT)
8289      vassert(condT == IRTemp_INVALID);
8290
8291   /* Data processing:
8292      Thumb: 111U 1111 AAAA Axxx xxxx BBBB CCCC xxxx
8293      ARM:   1111 001U AAAA Axxx xxxx BBBB CCCC xxxx
8294   */
8295   if (!isT && INSN(31,25) == BITS7(1,1,1,1,0,0,1)) {
8296      // ARM, DP
8297      return dis_neon_data_processing(INSN(31,0), condT);
8298   }
8299   if (isT && INSN(31,29) == BITS3(1,1,1)
8300       && INSN(27,24) == BITS4(1,1,1,1)) {
8301      // Thumb, DP
8302      UInt reformatted = INSN(23,0);
8303      reformatted |= (INSN(28,28) << 24); // U bit
8304      reformatted |= (BITS7(1,1,1,1,0,0,1) << 25);
8305      return dis_neon_data_processing(reformatted, condT);
8306   }
8307
8308   /* Load/store:
8309      Thumb: 1111 1001 AxL0 xxxx xxxx BBBB xxxx xxxx
8310      ARM:   1111 0100 AxL0 xxxx xxxx BBBB xxxx xxxx
8311   */
8312   if (!isT && INSN(31,24) == BITS8(1,1,1,1,0,1,0,0)) {
8313      // ARM, memory
8314      return dis_neon_load_or_store(INSN(31,0), isT, condT);
8315   }
8316   if (isT && INSN(31,24) == BITS8(1,1,1,1,1,0,0,1)) {
8317      UInt reformatted = INSN(23,0);
8318      reformatted |= (BITS8(1,1,1,1,0,1,0,0) << 24);
8319      return dis_neon_load_or_store(reformatted, isT, condT);
8320   }
8321
8322   /* Doesn't match. */
8323   return False;
8324
8325#  undef INSN
8326}
8327
8328
8329/*------------------------------------------------------------*/
8330/*--- V6 MEDIA instructions                                ---*/
8331/*------------------------------------------------------------*/
8332
8333/* Both ARM and Thumb */
8334
8335/* Translate a V6 media instruction.    If successful, returns
8336   True and *dres may or may not be updated.  If failure, returns
8337   False and doesn't change *dres nor create any IR.
8338
8339   The Thumb and ARM encodings are completely different.  In Thumb
8340   mode, the caller must pass the entire 32 bits.  In ARM mode it must
8341   pass the lower 28 bits.  Apart from that, callers may pass any
8342   instruction; this function ignores anything it doesn't recognise.
8343
8344   Caller must supply an IRTemp 'condT' holding the gating condition,
8345   or IRTemp_INVALID indicating the insn is always executed.
8346
8347   Caller must also supply an ARMCondcode 'cond'.  This is only used
8348   for debug printing, no other purpose.  For ARM, this is simply the
8349   top 4 bits of the original instruction.  For Thumb, the condition
8350   is not (really) known until run time, and so ARMCondAL should be
8351   passed, only so that printing of these instructions does not show
8352   any condition.
8353
8354   Finally, the caller must indicate whether this occurs in ARM or in
8355   Thumb code.
8356*/
8357static Bool decode_V6MEDIA_instruction (
8358               /*MOD*/DisResult* dres,
8359               UInt              insnv6m,
8360               IRTemp            condT,
8361               ARMCondcode       conq,
8362               Bool              isT
8363            )
8364{
8365#  define INSNA(_bMax,_bMin)   SLICE_UInt(insnv6m, (_bMax), (_bMin))
8366#  define INSNT0(_bMax,_bMin)  SLICE_UInt( ((insnv6m >> 16) & 0xFFFF), \
8367                                           (_bMax), (_bMin) )
8368#  define INSNT1(_bMax,_bMin)  SLICE_UInt( ((insnv6m >> 0)  & 0xFFFF), \
8369                                           (_bMax), (_bMin) )
8370   HChar dis_buf[128];
8371   dis_buf[0] = 0;
8372
8373   if (isT) {
8374      vassert(conq == ARMCondAL);
8375   } else {
8376      vassert(INSNA(31,28) == BITS4(0,0,0,0)); // caller's obligation
8377      vassert(conq >= ARMCondEQ && conq <= ARMCondAL);
8378   }
8379
8380   /* ----------- smulbb, smulbt, smultb, smultt ----------- */
8381   {
8382     UInt regD = 99, regM = 99, regN = 99, bitM = 0, bitN = 0;
8383     Bool gate = False;
8384
8385     if (isT) {
8386        if (INSNT0(15,4) == 0xFB1 && INSNT1(15,12) == BITS4(1,1,1,1)
8387            && INSNT1(7,6) == BITS2(0,0)) {
8388           regD = INSNT1(11,8);
8389           regM = INSNT1(3,0);
8390           regN = INSNT0(3,0);
8391           bitM = INSNT1(4,4);
8392           bitN = INSNT1(5,5);
8393           if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
8394              gate = True;
8395        }
8396     } else {
8397        if (BITS8(0,0,0,1,0,1,1,0) == INSNA(27,20) &&
8398            BITS4(0,0,0,0)         == INSNA(15,12) &&
8399            BITS4(1,0,0,0)         == (INSNA(7,4) & BITS4(1,0,0,1)) ) {
8400           regD = INSNA(19,16);
8401           regM = INSNA(11,8);
8402           regN = INSNA(3,0);
8403           bitM = INSNA(6,6);
8404           bitN = INSNA(5,5);
8405           if (regD != 15 && regN != 15 && regM != 15)
8406              gate = True;
8407        }
8408     }
8409
8410     if (gate) {
8411        IRTemp srcN = newTemp(Ity_I32);
8412        IRTemp srcM = newTemp(Ity_I32);
8413        IRTemp res  = newTemp(Ity_I32);
8414
8415        assign( srcN, binop(Iop_Sar32,
8416                            binop(Iop_Shl32,
8417                                  isT ? getIRegT(regN) : getIRegA(regN),
8418                                  mkU8(bitN ? 0 : 16)), mkU8(16)) );
8419        assign( srcM, binop(Iop_Sar32,
8420                            binop(Iop_Shl32,
8421                                  isT ? getIRegT(regM) : getIRegA(regM),
8422                                  mkU8(bitM ? 0 : 16)), mkU8(16)) );
8423        assign( res, binop(Iop_Mul32, mkexpr(srcN), mkexpr(srcM)) );
8424
8425        if (isT)
8426           putIRegT( regD, mkexpr(res), condT );
8427        else
8428           putIRegA( regD, mkexpr(res), condT, Ijk_Boring );
8429
8430        DIP( "smul%c%c%s r%u, r%u, r%u\n", bitN ? 't' : 'b', bitM ? 't' : 'b',
8431             nCC(conq), regD, regN, regM );
8432        return True;
8433     }
8434     /* fall through */
8435   }
8436
8437   /* ------------ smulwb<y><c> <Rd>,<Rn>,<Rm> ------------- */
8438   /* ------------ smulwt<y><c> <Rd>,<Rn>,<Rm> ------------- */
8439   {
8440     UInt regD = 99, regN = 99, regM = 99, bitM = 0;
8441     Bool gate = False;
8442
8443     if (isT) {
8444        if (INSNT0(15,4) == 0xFB3 && INSNT1(15,12) == BITS4(1,1,1,1)
8445            && INSNT1(7,5) == BITS3(0,0,0)) {
8446          regN = INSNT0(3,0);
8447          regD = INSNT1(11,8);
8448          regM = INSNT1(3,0);
8449          bitM = INSNT1(4,4);
8450          if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
8451             gate = True;
8452        }
8453     } else {
8454        if (INSNA(27,20) == BITS8(0,0,0,1,0,0,1,0) &&
8455            INSNA(15,12) == BITS4(0,0,0,0)         &&
8456            (INSNA(7,4) & BITS4(1,0,1,1)) == BITS4(1,0,1,0)) {
8457           regD = INSNA(19,16);
8458           regN = INSNA(3,0);
8459           regM = INSNA(11,8);
8460           bitM = INSNA(6,6);
8461           if (regD != 15 && regN != 15 && regM != 15)
8462              gate = True;
8463        }
8464     }
8465
8466     if (gate) {
8467        IRTemp irt_prod = newTemp(Ity_I64);
8468
8469        assign( irt_prod,
8470                binop(Iop_MullS32,
8471                      isT ? getIRegT(regN) : getIRegA(regN),
8472                      binop(Iop_Sar32,
8473                            binop(Iop_Shl32,
8474                                  isT ? getIRegT(regM) : getIRegA(regM),
8475                                  mkU8(bitM ? 0 : 16)),
8476                            mkU8(16))) );
8477
8478        IRExpr* ire_result = binop(Iop_Or32,
8479                                   binop( Iop_Shl32,
8480                                          unop(Iop_64HIto32, mkexpr(irt_prod)),
8481                                          mkU8(16) ),
8482                                   binop( Iop_Shr32,
8483                                          unop(Iop_64to32, mkexpr(irt_prod)),
8484                                          mkU8(16) ) );
8485
8486        if (isT)
8487           putIRegT( regD, ire_result, condT );
8488        else
8489           putIRegA( regD, ire_result, condT, Ijk_Boring );
8490
8491        DIP("smulw%c%s r%u, r%u, r%u\n",
8492            bitM ? 't' : 'b', nCC(conq),regD,regN,regM);
8493        return True;
8494     }
8495     /* fall through */
8496   }
8497
8498   /* ------------ pkhbt<c> Rd, Rn, Rm {,LSL #imm} ------------- */
8499   /* ------------ pkhtb<c> Rd, Rn, Rm {,ASR #imm} ------------- */
8500   {
8501     UInt regD = 99, regN = 99, regM = 99, imm5 = 99, shift_type = 99;
8502     Bool tbform = False;
8503     Bool gate = False;
8504
8505     if (isT) {
8506        if (INSNT0(15,4) == 0xEAC
8507            && INSNT1(15,15) == 0 && INSNT1(4,4) == 0) {
8508           regN = INSNT0(3,0);
8509           regD = INSNT1(11,8);
8510           regM = INSNT1(3,0);
8511           imm5 = (INSNT1(14,12) << 2) | INSNT1(7,6);
8512           shift_type = (INSNT1(5,5) << 1) | 0;
8513           tbform = (INSNT1(5,5) == 0) ? False : True;
8514           if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
8515              gate = True;
8516        }
8517     } else {
8518        if (INSNA(27,20) == BITS8(0,1,1,0,1,0,0,0) &&
8519            INSNA(5,4)   == BITS2(0,1)             &&
8520            (INSNA(6,6)  == 0 || INSNA(6,6) == 1) ) {
8521           regD = INSNA(15,12);
8522           regN = INSNA(19,16);
8523           regM = INSNA(3,0);
8524           imm5 = INSNA(11,7);
8525           shift_type = (INSNA(6,6) << 1) | 0;
8526           tbform = (INSNA(6,6) == 0) ? False : True;
8527           if (regD != 15 && regN != 15 && regM != 15)
8528              gate = True;
8529        }
8530     }
8531
8532     if (gate) {
8533        IRTemp irt_regM       = newTemp(Ity_I32);
8534        IRTemp irt_regM_shift = newTemp(Ity_I32);
8535        assign( irt_regM, isT ? getIRegT(regM) : getIRegA(regM) );
8536        compute_result_and_C_after_shift_by_imm5(
8537           dis_buf, &irt_regM_shift, NULL, irt_regM, shift_type, imm5, regM );
8538
8539        UInt mask = (tbform == True) ? 0x0000FFFF : 0xFFFF0000;
8540        IRExpr* ire_result
8541          = binop( Iop_Or32,
8542                   binop(Iop_And32, mkexpr(irt_regM_shift), mkU32(mask)),
8543                   binop(Iop_And32, isT ? getIRegT(regN) : getIRegA(regN),
8544                                    unop(Iop_Not32, mkU32(mask))) );
8545
8546        if (isT)
8547           putIRegT( regD, ire_result, condT );
8548        else
8549           putIRegA( regD, ire_result, condT, Ijk_Boring );
8550
8551        DIP( "pkh%s%s r%u, r%u, r%u %s\n", tbform ? "tb" : "bt",
8552             nCC(conq), regD, regN, regM, dis_buf );
8553
8554        return True;
8555     }
8556     /* fall through */
8557   }
8558
8559   /* ---------- usat<c> <Rd>,#<imm5>,<Rn>{,<shift>} ----------- */
8560   {
8561     UInt regD = 99, regN = 99, shift_type = 99, imm5 = 99, sat_imm = 99;
8562     Bool gate = False;
8563
8564     if (isT) {
8565        if (INSNT0(15,6) == BITS10(1,1,1,1,0,0,1,1,1,0)
8566            && INSNT0(4,4) == 0
8567            && INSNT1(15,15) == 0 && INSNT1(5,5) == 0) {
8568           regD       = INSNT1(11,8);
8569           regN       = INSNT0(3,0);
8570           shift_type = (INSNT0(5,5) << 1) | 0;
8571           imm5       = (INSNT1(14,12) << 2) | INSNT1(7,6);
8572           sat_imm    = INSNT1(4,0);
8573           if (!isBadRegT(regD) && !isBadRegT(regN))
8574              gate = True;
8575           if (shift_type == BITS2(1,0) && imm5 == 0)
8576              gate = False;
8577        }
8578     } else {
8579        if (INSNA(27,21) == BITS7(0,1,1,0,1,1,1) &&
8580            INSNA(5,4)   == BITS2(0,1)) {
8581           regD       = INSNA(15,12);
8582           regN       = INSNA(3,0);
8583           shift_type = (INSNA(6,6) << 1) | 0;
8584           imm5       = INSNA(11,7);
8585           sat_imm    = INSNA(20,16);
8586           if (regD != 15 && regN != 15)
8587              gate = True;
8588        }
8589     }
8590
8591     if (gate) {
8592        IRTemp irt_regN       = newTemp(Ity_I32);
8593        IRTemp irt_regN_shift = newTemp(Ity_I32);
8594        IRTemp irt_sat_Q      = newTemp(Ity_I32);
8595        IRTemp irt_result     = newTemp(Ity_I32);
8596
8597        assign( irt_regN, isT ? getIRegT(regN) : getIRegA(regN) );
8598        compute_result_and_C_after_shift_by_imm5(
8599                dis_buf, &irt_regN_shift, NULL,
8600                irt_regN, shift_type, imm5, regN );
8601
8602        armUnsignedSatQ( &irt_result, &irt_sat_Q, irt_regN_shift, sat_imm );
8603        or_into_QFLAG32( mkexpr(irt_sat_Q), condT );
8604
8605        if (isT)
8606           putIRegT( regD, mkexpr(irt_result), condT );
8607        else
8608           putIRegA( regD, mkexpr(irt_result), condT, Ijk_Boring );
8609
8610        DIP("usat%s r%u, #0x%04x, %s\n",
8611            nCC(conq), regD, imm5, dis_buf);
8612        return True;
8613     }
8614     /* fall through */
8615   }
8616
8617  /* ----------- ssat<c> <Rd>,#<imm5>,<Rn>{,<shift>} ----------- */
8618   {
8619     UInt regD = 99, regN = 99, shift_type = 99, imm5 = 99, sat_imm = 99;
8620     Bool gate = False;
8621
8622     if (isT) {
8623        if (INSNT0(15,6) == BITS10(1,1,1,1,0,0,1,1,0,0)
8624            && INSNT0(4,4) == 0
8625            && INSNT1(15,15) == 0 && INSNT1(5,5) == 0) {
8626           regD       = INSNT1(11,8);
8627           regN       = INSNT0(3,0);
8628           shift_type = (INSNT0(5,5) << 1) | 0;
8629           imm5       = (INSNT1(14,12) << 2) | INSNT1(7,6);
8630           sat_imm    = INSNT1(4,0) + 1;
8631           if (!isBadRegT(regD) && !isBadRegT(regN))
8632              gate = True;
8633           if (shift_type == BITS2(1,0) && imm5 == 0)
8634              gate = False;
8635        }
8636     } else {
8637        if (INSNA(27,21) == BITS7(0,1,1,0,1,0,1) &&
8638            INSNA(5,4)   == BITS2(0,1)) {
8639           regD       = INSNA(15,12);
8640           regN       = INSNA(3,0);
8641           shift_type = (INSNA(6,6) << 1) | 0;
8642           imm5       = INSNA(11,7);
8643           sat_imm    = INSNA(20,16) + 1;
8644           if (regD != 15 && regN != 15)
8645              gate = True;
8646        }
8647     }
8648
8649     if (gate) {
8650        IRTemp irt_regN       = newTemp(Ity_I32);
8651        IRTemp irt_regN_shift = newTemp(Ity_I32);
8652        IRTemp irt_sat_Q      = newTemp(Ity_I32);
8653        IRTemp irt_result     = newTemp(Ity_I32);
8654
8655        assign( irt_regN, isT ? getIRegT(regN) : getIRegA(regN) );
8656        compute_result_and_C_after_shift_by_imm5(
8657                dis_buf, &irt_regN_shift, NULL,
8658                irt_regN, shift_type, imm5, regN );
8659
8660        armSignedSatQ( irt_regN_shift, sat_imm, &irt_result, &irt_sat_Q );
8661        or_into_QFLAG32( mkexpr(irt_sat_Q), condT );
8662
8663        if (isT)
8664           putIRegT( regD, mkexpr(irt_result), condT );
8665        else
8666           putIRegA( regD, mkexpr(irt_result), condT, Ijk_Boring );
8667
8668        DIP( "ssat%s r%u, #0x%04x, %s\n",
8669             nCC(conq), regD, imm5, dis_buf);
8670        return True;
8671    }
8672    /* fall through */
8673  }
8674
8675   /* -------------- usat16<c> <Rd>,#<imm4>,<Rn> --------------- */
8676   {
8677     UInt regD = 99, regN = 99, sat_imm = 99;
8678     Bool gate = False;
8679
8680     if (isT) {
8681        if (INSNT0(15,4) == 0xF3A && (INSNT1(15,0) & 0xF0F0) == 0x0000) {
8682           regN = INSNT0(3,0);
8683           regD = INSNT1(11,8);
8684           sat_imm = INSNT1(3,0);
8685           if (!isBadRegT(regD) && !isBadRegT(regN))
8686              gate = True;
8687       }
8688     } else {
8689        if (INSNA(27,20) == BITS8(0,1,1,0,1,1,1,0) &&
8690            INSNA(11,8)  == BITS4(1,1,1,1)         &&
8691            INSNA(7,4)   == BITS4(0,0,1,1)) {
8692           regD    = INSNA(15,12);
8693           regN    = INSNA(3,0);
8694           sat_imm = INSNA(19,16);
8695           if (regD != 15 && regN != 15)
8696              gate = True;
8697        }
8698     }
8699
8700     if (gate) {
8701        IRTemp irt_regN    = newTemp(Ity_I32);
8702        IRTemp irt_regN_lo = newTemp(Ity_I32);
8703        IRTemp irt_regN_hi = newTemp(Ity_I32);
8704        IRTemp irt_Q_lo    = newTemp(Ity_I32);
8705        IRTemp irt_Q_hi    = newTemp(Ity_I32);
8706        IRTemp irt_res_lo  = newTemp(Ity_I32);
8707        IRTemp irt_res_hi  = newTemp(Ity_I32);
8708
8709        assign( irt_regN, isT ? getIRegT(regN) : getIRegA(regN) );
8710        assign( irt_regN_lo, binop( Iop_Sar32,
8711                                    binop(Iop_Shl32, mkexpr(irt_regN), mkU8(16)),
8712                                    mkU8(16)) );
8713        assign( irt_regN_hi, binop(Iop_Sar32, mkexpr(irt_regN), mkU8(16)) );
8714
8715        armUnsignedSatQ( &irt_res_lo, &irt_Q_lo, irt_regN_lo, sat_imm );
8716        or_into_QFLAG32( mkexpr(irt_Q_lo), condT );
8717
8718        armUnsignedSatQ( &irt_res_hi, &irt_Q_hi, irt_regN_hi, sat_imm );
8719        or_into_QFLAG32( mkexpr(irt_Q_hi), condT );
8720
8721        IRExpr* ire_result = binop( Iop_Or32,
8722                                    binop(Iop_Shl32, mkexpr(irt_res_hi), mkU8(16)),
8723                                    mkexpr(irt_res_lo) );
8724
8725        if (isT)
8726           putIRegT( regD, ire_result, condT );
8727        else
8728           putIRegA( regD, ire_result, condT, Ijk_Boring );
8729
8730        DIP( "usat16%s r%u, #0x%04x, r%u\n", nCC(conq), regD, sat_imm, regN );
8731        return True;
8732     }
8733     /* fall through */
8734   }
8735
8736   /* -------------- uadd16<c> <Rd>,<Rn>,<Rm> -------------- */
8737   {
8738     UInt regD = 99, regN = 99, regM = 99;
8739     Bool gate = False;
8740
8741     if (isT) {
8742        if (INSNT0(15,4) == 0xFA9 && (INSNT1(15,0) & 0xF0F0) == 0xF040) {
8743           regN = INSNT0(3,0);
8744           regD = INSNT1(11,8);
8745           regM = INSNT1(3,0);
8746           if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
8747              gate = True;
8748        }
8749     } else {
8750        if (INSNA(27,20) == BITS8(0,1,1,0,0,1,0,1) &&
8751            INSNA(11,8)  == BITS4(1,1,1,1)         &&
8752            INSNA(7,4)   == BITS4(0,0,0,1)) {
8753           regD = INSNA(15,12);
8754           regN = INSNA(19,16);
8755           regM = INSNA(3,0);
8756           if (regD != 15 && regN != 15 && regM != 15)
8757              gate = True;
8758        }
8759     }
8760
8761     if (gate) {
8762        IRTemp rNt  = newTemp(Ity_I32);
8763        IRTemp rMt  = newTemp(Ity_I32);
8764        IRTemp res  = newTemp(Ity_I32);
8765        IRTemp reso = newTemp(Ity_I32);
8766
8767        assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) );
8768        assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) );
8769
8770        assign(res, binop(Iop_Add16x2, mkexpr(rNt), mkexpr(rMt)));
8771        if (isT)
8772           putIRegT( regD, mkexpr(res), condT );
8773        else
8774           putIRegA( regD, mkexpr(res), condT, Ijk_Boring );
8775
8776        assign(reso, binop(Iop_HAdd16Ux2, mkexpr(rNt), mkexpr(rMt)));
8777        set_GE_32_10_from_bits_31_15(reso, condT);
8778
8779        DIP("uadd16%s r%u, r%u, r%u\n", nCC(conq),regD,regN,regM);
8780        return True;
8781     }
8782     /* fall through */
8783   }
8784
8785   /* -------------- sadd16<c> <Rd>,<Rn>,<Rm> -------------- */
8786   {
8787     UInt regD = 99, regN = 99, regM = 99;
8788     Bool gate = False;
8789
8790     if (isT) {
8791        if (INSNT0(15,4) == 0xFA9 && (INSNT1(15,0) & 0xF0F0) == 0xF000) {
8792           regN = INSNT0(3,0);
8793           regD = INSNT1(11,8);
8794           regM = INSNT1(3,0);
8795           if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
8796              gate = True;
8797        }
8798     } else {
8799        if (INSNA(27,20) == BITS8(0,1,1,0,0,0,0,1) &&
8800            INSNA(11,8)  == BITS4(1,1,1,1)         &&
8801            INSNA(7,4)   == BITS4(0,0,0,1)) {
8802           regD = INSNA(15,12);
8803           regN = INSNA(19,16);
8804           regM = INSNA(3,0);
8805           if (regD != 15 && regN != 15 && regM != 15)
8806              gate = True;
8807        }
8808     }
8809
8810     if (gate) {
8811        IRTemp rNt  = newTemp(Ity_I32);
8812        IRTemp rMt  = newTemp(Ity_I32);
8813        IRTemp res  = newTemp(Ity_I32);
8814        IRTemp reso = newTemp(Ity_I32);
8815
8816        assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) );
8817        assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) );
8818
8819        assign(res, binop(Iop_Add16x2, mkexpr(rNt), mkexpr(rMt)));
8820        if (isT)
8821           putIRegT( regD, mkexpr(res), condT );
8822        else
8823           putIRegA( regD, mkexpr(res), condT, Ijk_Boring );
8824
8825        assign(reso, unop(Iop_Not32,
8826                          binop(Iop_HAdd16Sx2, mkexpr(rNt), mkexpr(rMt))));
8827        set_GE_32_10_from_bits_31_15(reso, condT);
8828
8829        DIP("sadd16%s r%u, r%u, r%u\n", nCC(conq),regD,regN,regM);
8830        return True;
8831     }
8832     /* fall through */
8833   }
8834
8835   /* ---------------- usub16<c> <Rd>,<Rn>,<Rm> ---------------- */
8836   {
8837     UInt regD = 99, regN = 99, regM = 99;
8838     Bool gate = False;
8839
8840     if (isT) {
8841        if (INSNT0(15,4) == 0xFAD && (INSNT1(15,0) & 0xF0F0) == 0xF040) {
8842           regN = INSNT0(3,0);
8843           regD = INSNT1(11,8);
8844           regM = INSNT1(3,0);
8845           if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
8846              gate = True;
8847        }
8848     } else {
8849        if (INSNA(27,20) == BITS8(0,1,1,0,0,1,0,1) &&
8850            INSNA(11,8)  == BITS4(1,1,1,1)         &&
8851            INSNA(7,4)   == BITS4(0,1,1,1)) {
8852           regD = INSNA(15,12);
8853           regN = INSNA(19,16);
8854           regM = INSNA(3,0);
8855           if (regD != 15 && regN != 15 && regM != 15)
8856             gate = True;
8857        }
8858     }
8859
8860     if (gate) {
8861        IRTemp rNt  = newTemp(Ity_I32);
8862        IRTemp rMt  = newTemp(Ity_I32);
8863        IRTemp res  = newTemp(Ity_I32);
8864        IRTemp reso = newTemp(Ity_I32);
8865
8866        assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) );
8867        assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) );
8868
8869        assign(res, binop(Iop_Sub16x2, mkexpr(rNt), mkexpr(rMt)));
8870        if (isT)
8871           putIRegT( regD, mkexpr(res), condT );
8872        else
8873           putIRegA( regD, mkexpr(res), condT, Ijk_Boring );
8874
8875        assign(reso, unop(Iop_Not32,
8876                          binop(Iop_HSub16Ux2, mkexpr(rNt), mkexpr(rMt))));
8877        set_GE_32_10_from_bits_31_15(reso, condT);
8878
8879        DIP("usub16%s r%u, r%u, r%u\n", nCC(conq),regD,regN,regM);
8880        return True;
8881     }
8882     /* fall through */
8883   }
8884
8885   /* -------------- ssub16<c> <Rd>,<Rn>,<Rm> -------------- */
8886   {
8887     UInt regD = 99, regN = 99, regM = 99;
8888     Bool gate = False;
8889
8890     if (isT) {
8891        if (INSNT0(15,4) == 0xFAD && (INSNT1(15,0) & 0xF0F0) == 0xF000) {
8892           regN = INSNT0(3,0);
8893           regD = INSNT1(11,8);
8894           regM = INSNT1(3,0);
8895           if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
8896              gate = True;
8897        }
8898     } else {
8899        if (INSNA(27,20) == BITS8(0,1,1,0,0,0,0,1) &&
8900            INSNA(11,8)  == BITS4(1,1,1,1)         &&
8901            INSNA(7,4)   == BITS4(0,1,1,1)) {
8902           regD = INSNA(15,12);
8903           regN = INSNA(19,16);
8904           regM = INSNA(3,0);
8905           if (regD != 15 && regN != 15 && regM != 15)
8906              gate = True;
8907        }
8908     }
8909
8910     if (gate) {
8911        IRTemp rNt  = newTemp(Ity_I32);
8912        IRTemp rMt  = newTemp(Ity_I32);
8913        IRTemp res  = newTemp(Ity_I32);
8914        IRTemp reso = newTemp(Ity_I32);
8915
8916        assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) );
8917        assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) );
8918
8919        assign(res, binop(Iop_Sub16x2, mkexpr(rNt), mkexpr(rMt)));
8920        if (isT)
8921           putIRegT( regD, mkexpr(res), condT );
8922        else
8923           putIRegA( regD, mkexpr(res), condT, Ijk_Boring );
8924
8925        assign(reso, unop(Iop_Not32,
8926                          binop(Iop_HSub16Sx2, mkexpr(rNt), mkexpr(rMt))));
8927        set_GE_32_10_from_bits_31_15(reso, condT);
8928
8929        DIP("ssub16%s r%u, r%u, r%u\n", nCC(conq),regD,regN,regM);
8930        return True;
8931     }
8932     /* fall through */
8933   }
8934
8935   /* ----------------- uadd8<c> <Rd>,<Rn>,<Rm> ---------------- */
8936   {
8937     UInt regD = 99, regN = 99, regM = 99;
8938     Bool gate = False;
8939
8940     if (isT) {
8941        if (INSNT0(15,4) == 0xFA8 && (INSNT1(15,0) & 0xF0F0) == 0xF040) {
8942           regN = INSNT0(3,0);
8943           regD = INSNT1(11,8);
8944           regM = INSNT1(3,0);
8945           if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
8946              gate = True;
8947        }
8948     } else {
8949        if (INSNA(27,20) == BITS8(0,1,1,0,0,1,0,1) &&
8950            INSNA(11,8)  == BITS4(1,1,1,1)         &&
8951            (INSNA(7,4)  == BITS4(1,0,0,1))) {
8952           regD = INSNA(15,12);
8953           regN = INSNA(19,16);
8954           regM = INSNA(3,0);
8955           if (regD != 15 && regN != 15 && regM != 15)
8956              gate = True;
8957        }
8958     }
8959
8960     if (gate) {
8961        IRTemp rNt  = newTemp(Ity_I32);
8962        IRTemp rMt  = newTemp(Ity_I32);
8963        IRTemp res  = newTemp(Ity_I32);
8964        IRTemp reso = newTemp(Ity_I32);
8965
8966        assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) );
8967        assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) );
8968
8969        assign(res, binop(Iop_Add8x4, mkexpr(rNt), mkexpr(rMt)));
8970        if (isT)
8971           putIRegT( regD, mkexpr(res), condT );
8972        else
8973           putIRegA( regD, mkexpr(res), condT, Ijk_Boring );
8974
8975        assign(reso, binop(Iop_HAdd8Ux4, mkexpr(rNt), mkexpr(rMt)));
8976        set_GE_3_2_1_0_from_bits_31_23_15_7(reso, condT);
8977
8978        DIP("uadd8%s r%u, r%u, r%u\n", nCC(conq),regD,regN,regM);
8979        return True;
8980     }
8981     /* fall through */
8982   }
8983
8984   /* ------------------- sadd8<c> <Rd>,<Rn>,<Rm> ------------------ */
8985   {
8986     UInt regD = 99, regN = 99, regM = 99;
8987     Bool gate = False;
8988
8989     if (isT) {
8990        if (INSNT0(15,4) == 0xFA8 && (INSNT1(15,0) & 0xF0F0) == 0xF000) {
8991           regN = INSNT0(3,0);
8992           regD = INSNT1(11,8);
8993           regM = INSNT1(3,0);
8994           if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
8995              gate = True;
8996        }
8997     } else {
8998        if (INSNA(27,20) == BITS8(0,1,1,0,0,0,0,1) &&
8999            INSNA(11,8)  == BITS4(1,1,1,1)         &&
9000            (INSNA(7,4)  == BITS4(1,0,0,1))) {
9001           regD = INSNA(15,12);
9002           regN = INSNA(19,16);
9003           regM = INSNA(3,0);
9004           if (regD != 15 && regN != 15 && regM != 15)
9005              gate = True;
9006        }
9007     }
9008
9009     if (gate) {
9010        IRTemp rNt  = newTemp(Ity_I32);
9011        IRTemp rMt  = newTemp(Ity_I32);
9012        IRTemp res  = newTemp(Ity_I32);
9013        IRTemp reso = newTemp(Ity_I32);
9014
9015        assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) );
9016        assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) );
9017
9018        assign(res, binop(Iop_Add8x4, mkexpr(rNt), mkexpr(rMt)));
9019        if (isT)
9020           putIRegT( regD, mkexpr(res), condT );
9021        else
9022           putIRegA( regD, mkexpr(res), condT, Ijk_Boring );
9023
9024        assign(reso, unop(Iop_Not32,
9025                          binop(Iop_HAdd8Sx4, mkexpr(rNt), mkexpr(rMt))));
9026        set_GE_3_2_1_0_from_bits_31_23_15_7(reso, condT);
9027
9028        DIP("sadd8%s r%u, r%u, r%u\n", nCC(conq),regD,regN,regM);
9029        return True;
9030     }
9031     /* fall through */
9032   }
9033
9034   /* ------------------- usub8<c> <Rd>,<Rn>,<Rm> ------------------ */
9035   {
9036     UInt regD = 99, regN = 99, regM = 99;
9037     Bool gate = False;
9038
9039     if (isT) {
9040        if (INSNT0(15,4) == 0xFAC && (INSNT1(15,0) & 0xF0F0) == 0xF040) {
9041           regN = INSNT0(3,0);
9042           regD = INSNT1(11,8);
9043           regM = INSNT1(3,0);
9044           if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
9045              gate = True;
9046        }
9047     } else {
9048        if (INSNA(27,20) == BITS8(0,1,1,0,0,1,0,1) &&
9049            INSNA(11,8)  == BITS4(1,1,1,1)         &&
9050            (INSNA(7,4)  == BITS4(1,1,1,1))) {
9051           regD = INSNA(15,12);
9052           regN = INSNA(19,16);
9053           regM = INSNA(3,0);
9054           if (regD != 15 && regN != 15 && regM != 15)
9055             gate = True;
9056        }
9057     }
9058
9059     if (gate) {
9060        IRTemp rNt  = newTemp(Ity_I32);
9061        IRTemp rMt  = newTemp(Ity_I32);
9062        IRTemp res  = newTemp(Ity_I32);
9063        IRTemp reso = newTemp(Ity_I32);
9064
9065        assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) );
9066        assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) );
9067
9068        assign(res, binop(Iop_Sub8x4, mkexpr(rNt), mkexpr(rMt)));
9069        if (isT)
9070           putIRegT( regD, mkexpr(res), condT );
9071        else
9072           putIRegA( regD, mkexpr(res), condT, Ijk_Boring );
9073
9074        assign(reso, unop(Iop_Not32,
9075                          binop(Iop_HSub8Ux4, mkexpr(rNt), mkexpr(rMt))));
9076        set_GE_3_2_1_0_from_bits_31_23_15_7(reso, condT);
9077
9078        DIP("usub8%s r%u, r%u, r%u\n", nCC(conq),regD,regN,regM);
9079        return True;
9080     }
9081     /* fall through */
9082   }
9083
9084   /* ------------------- ssub8<c> <Rd>,<Rn>,<Rm> ------------------ */
9085   {
9086     UInt regD = 99, regN = 99, regM = 99;
9087     Bool gate = False;
9088
9089     if (isT) {
9090        if (INSNT0(15,4) == 0xFAC && (INSNT1(15,0) & 0xF0F0) == 0xF000) {
9091           regN = INSNT0(3,0);
9092           regD = INSNT1(11,8);
9093           regM = INSNT1(3,0);
9094           if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
9095              gate = True;
9096        }
9097     } else {
9098        if (INSNA(27,20) == BITS8(0,1,1,0,0,0,0,1) &&
9099            INSNA(11,8)  == BITS4(1,1,1,1)         &&
9100            INSNA(7,4)   == BITS4(1,1,1,1)) {
9101           regD = INSNA(15,12);
9102           regN = INSNA(19,16);
9103           regM = INSNA(3,0);
9104           if (regD != 15 && regN != 15 && regM != 15)
9105              gate = True;
9106        }
9107     }
9108
9109     if (gate) {
9110        IRTemp rNt  = newTemp(Ity_I32);
9111        IRTemp rMt  = newTemp(Ity_I32);
9112        IRTemp res  = newTemp(Ity_I32);
9113        IRTemp reso = newTemp(Ity_I32);
9114
9115        assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) );
9116        assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) );
9117
9118        assign(res, binop(Iop_Sub8x4, mkexpr(rNt), mkexpr(rMt)));
9119        if (isT)
9120           putIRegT( regD, mkexpr(res), condT );
9121        else
9122           putIRegA( regD, mkexpr(res), condT, Ijk_Boring );
9123
9124        assign(reso, unop(Iop_Not32,
9125                          binop(Iop_HSub8Sx4, mkexpr(rNt), mkexpr(rMt))));
9126        set_GE_3_2_1_0_from_bits_31_23_15_7(reso, condT);
9127
9128        DIP("ssub8%s r%u, r%u, r%u\n", nCC(conq),regD,regN,regM);
9129        return True;
9130     }
9131     /* fall through */
9132   }
9133
9134   /* ------------------ qadd8<c> <Rd>,<Rn>,<Rm> ------------------- */
9135   {
9136     UInt regD = 99, regN = 99, regM = 99;
9137     Bool gate = False;
9138
9139     if (isT) {
9140        if (INSNT0(15,4) == 0xFA8 && (INSNT1(15,0) & 0xF0F0) == 0xF010) {
9141           regN = INSNT0(3,0);
9142           regD = INSNT1(11,8);
9143           regM = INSNT1(3,0);
9144           if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
9145              gate = True;
9146        }
9147     } else {
9148        if (INSNA(27,20) == BITS8(0,1,1,0,0,0,1,0) &&
9149            INSNA(11,8)  == BITS4(1,1,1,1)         &&
9150            INSNA(7,4)   == BITS4(1,0,0,1)) {
9151           regD = INSNA(15,12);
9152           regN = INSNA(19,16);
9153           regM = INSNA(3,0);
9154           if (regD != 15 && regN != 15 && regM != 15)
9155              gate = True;
9156        }
9157     }
9158
9159     if (gate) {
9160        IRTemp rNt   = newTemp(Ity_I32);
9161        IRTemp rMt   = newTemp(Ity_I32);
9162        IRTemp res_q = newTemp(Ity_I32);
9163
9164        assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) );
9165        assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) );
9166
9167        assign(res_q, binop(Iop_QAdd8Sx4, mkexpr(rNt), mkexpr(rMt)));
9168        if (isT)
9169           putIRegT( regD, mkexpr(res_q), condT );
9170        else
9171           putIRegA( regD, mkexpr(res_q), condT, Ijk_Boring );
9172
9173        DIP("qadd8%s r%u, r%u, r%u\n", nCC(conq),regD,regN,regM);
9174        return True;
9175     }
9176     /* fall through */
9177   }
9178
9179   /* ------------------ qsub8<c> <Rd>,<Rn>,<Rm> ------------------- */
9180   {
9181     UInt regD = 99, regN = 99, regM = 99;
9182     Bool gate = False;
9183
9184     if (isT) {
9185        if (INSNT0(15,4) == 0xFAC && (INSNT1(15,0) & 0xF0F0) == 0xF010) {
9186           regN = INSNT0(3,0);
9187           regD = INSNT1(11,8);
9188           regM = INSNT1(3,0);
9189           if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
9190              gate = True;
9191        }
9192     } else {
9193        if (INSNA(27,20) == BITS8(0,1,1,0,0,0,1,0) &&
9194            INSNA(11,8)  == BITS4(1,1,1,1)         &&
9195            INSNA(7,4)   == BITS4(1,1,1,1)) {
9196           regD = INSNA(15,12);
9197           regN = INSNA(19,16);
9198           regM = INSNA(3,0);
9199           if (regD != 15 && regN != 15 && regM != 15)
9200              gate = True;
9201        }
9202     }
9203
9204     if (gate) {
9205        IRTemp rNt   = newTemp(Ity_I32);
9206        IRTemp rMt   = newTemp(Ity_I32);
9207        IRTemp res_q = newTemp(Ity_I32);
9208
9209        assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) );
9210        assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) );
9211
9212        assign(res_q, binop(Iop_QSub8Sx4, mkexpr(rNt), mkexpr(rMt)));
9213        if (isT)
9214           putIRegT( regD, mkexpr(res_q), condT );
9215        else
9216           putIRegA( regD, mkexpr(res_q), condT, Ijk_Boring );
9217
9218        DIP("qsub8%s r%u, r%u, r%u\n", nCC(conq),regD,regN,regM);
9219        return True;
9220     }
9221     /* fall through */
9222   }
9223
9224   /* ------------------ uqadd8<c> <Rd>,<Rn>,<Rm> ------------------ */
9225   {
9226     UInt regD = 99, regN = 99, regM = 99;
9227     Bool gate = False;
9228
9229     if (isT) {
9230        if (INSNT0(15,4) == 0xFA8 && (INSNT1(15,0) & 0xF0F0) == 0xF050) {
9231           regN = INSNT0(3,0);
9232           regD = INSNT1(11,8);
9233           regM = INSNT1(3,0);
9234           if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
9235              gate = True;
9236        }
9237     } else {
9238        if (INSNA(27,20) == BITS8(0,1,1,0,0,1,1,0) &&
9239            INSNA(11,8)  == BITS4(1,1,1,1)         &&
9240            (INSNA(7,4)  == BITS4(1,0,0,1))) {
9241           regD = INSNA(15,12);
9242           regN = INSNA(19,16);
9243           regM = INSNA(3,0);
9244           if (regD != 15 && regN != 15 && regM != 15)
9245              gate = True;
9246        }
9247     }
9248
9249     if (gate) {
9250        IRTemp rNt   = newTemp(Ity_I32);
9251        IRTemp rMt   = newTemp(Ity_I32);
9252        IRTemp res_q = newTemp(Ity_I32);
9253
9254        assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) );
9255        assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) );
9256
9257        assign(res_q, binop(Iop_QAdd8Ux4, mkexpr(rNt), mkexpr(rMt)));
9258        if (isT)
9259           putIRegT( regD, mkexpr(res_q), condT );
9260        else
9261           putIRegA( regD, mkexpr(res_q), condT, Ijk_Boring );
9262
9263        DIP("uqadd8%s r%u, r%u, r%u\n", nCC(conq),regD,regN,regM);
9264        return True;
9265     }
9266     /* fall through */
9267   }
9268
9269   /* ------------------ uqsub8<c> <Rd>,<Rn>,<Rm> ------------------ */
9270   {
9271     UInt regD = 99, regN = 99, regM = 99;
9272     Bool gate = False;
9273
9274     if (isT) {
9275        if (INSNT0(15,4) == 0xFAC && (INSNT1(15,0) & 0xF0F0) == 0xF050) {
9276           regN = INSNT0(3,0);
9277           regD = INSNT1(11,8);
9278           regM = INSNT1(3,0);
9279           if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
9280              gate = True;
9281        }
9282     } else {
9283        if (INSNA(27,20) == BITS8(0,1,1,0,0,1,1,0) &&
9284            INSNA(11,8)  == BITS4(1,1,1,1)         &&
9285            (INSNA(7,4)  == BITS4(1,1,1,1))) {
9286           regD = INSNA(15,12);
9287           regN = INSNA(19,16);
9288           regM = INSNA(3,0);
9289           if (regD != 15 && regN != 15 && regM != 15)
9290             gate = True;
9291        }
9292     }
9293
9294     if (gate) {
9295        IRTemp rNt   = newTemp(Ity_I32);
9296        IRTemp rMt   = newTemp(Ity_I32);
9297        IRTemp res_q = newTemp(Ity_I32);
9298
9299        assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) );
9300        assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) );
9301
9302        assign(res_q, binop(Iop_QSub8Ux4, mkexpr(rNt), mkexpr(rMt)));
9303        if (isT)
9304           putIRegT( regD, mkexpr(res_q), condT );
9305        else
9306           putIRegA( regD, mkexpr(res_q), condT, Ijk_Boring );
9307
9308        DIP("uqsub8%s r%u, r%u, r%u\n", nCC(conq),regD,regN,regM);
9309        return True;
9310     }
9311     /* fall through */
9312   }
9313
9314   /* ----------------- uhadd8<c> <Rd>,<Rn>,<Rm> ------------------- */
9315   {
9316     UInt regD = 99, regN = 99, regM = 99;
9317     Bool gate = False;
9318
9319     if (isT) {
9320        if (INSNT0(15,4) == 0xFA8 && (INSNT1(15,0) & 0xF0F0) == 0xF060) {
9321           regN = INSNT0(3,0);
9322           regD = INSNT1(11,8);
9323           regM = INSNT1(3,0);
9324           if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
9325              gate = True;
9326        }
9327     } else {
9328        if (INSNA(27,20) == BITS8(0,1,1,0,0,1,1,1) &&
9329            INSNA(11,8)  == BITS4(1,1,1,1)         &&
9330            INSNA(7,4)   == BITS4(1,0,0,1)) {
9331           regD = INSNA(15,12);
9332           regN = INSNA(19,16);
9333           regM = INSNA(3,0);
9334           if (regD != 15 && regN != 15 && regM != 15)
9335              gate = True;
9336        }
9337     }
9338
9339     if (gate) {
9340        IRTemp rNt   = newTemp(Ity_I32);
9341        IRTemp rMt   = newTemp(Ity_I32);
9342        IRTemp res_q = newTemp(Ity_I32);
9343
9344        assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) );
9345        assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) );
9346
9347        assign(res_q, binop(Iop_HAdd8Ux4, mkexpr(rNt), mkexpr(rMt)));
9348        if (isT)
9349           putIRegT( regD, mkexpr(res_q), condT );
9350        else
9351           putIRegA( regD, mkexpr(res_q), condT, Ijk_Boring );
9352
9353        DIP("uhadd8%s r%u, r%u, r%u\n", nCC(conq),regD,regN,regM);
9354        return True;
9355     }
9356     /* fall through */
9357   }
9358
9359   /* ----------------- uhadd16<c> <Rd>,<Rn>,<Rm> ------------------- */
9360   {
9361     UInt regD = 99, regN = 99, regM = 99;
9362     Bool gate = False;
9363
9364     if (isT) {
9365        if (INSNT0(15,4) == 0xFA9 && (INSNT1(15,0) & 0xF0F0) == 0xF060) {
9366           regN = INSNT0(3,0);
9367           regD = INSNT1(11,8);
9368           regM = INSNT1(3,0);
9369           if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
9370              gate = True;
9371        }
9372     } else {
9373        if (INSNA(27,20) == BITS8(0,1,1,0,0,1,1,1) &&
9374            INSNA(11,8)  == BITS4(1,1,1,1)         &&
9375            INSNA(7,4)   == BITS4(0,0,0,1)) {
9376           regD = INSNA(15,12);
9377           regN = INSNA(19,16);
9378           regM = INSNA(3,0);
9379           if (regD != 15 && regN != 15 && regM != 15)
9380              gate = True;
9381        }
9382     }
9383
9384     if (gate) {
9385        IRTemp rNt   = newTemp(Ity_I32);
9386        IRTemp rMt   = newTemp(Ity_I32);
9387        IRTemp res_q = newTemp(Ity_I32);
9388
9389        assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) );
9390        assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) );
9391
9392        assign(res_q, binop(Iop_HAdd16Ux2, mkexpr(rNt), mkexpr(rMt)));
9393        if (isT)
9394           putIRegT( regD, mkexpr(res_q), condT );
9395        else
9396           putIRegA( regD, mkexpr(res_q), condT, Ijk_Boring );
9397
9398        DIP("uhadd16%s r%u, r%u, r%u\n", nCC(conq),regD,regN,regM);
9399        return True;
9400     }
9401     /* fall through */
9402   }
9403
9404   /* ----------------- shadd8<c> <Rd>,<Rn>,<Rm> ------------------- */
9405   {
9406     UInt regD = 99, regN = 99, regM = 99;
9407     Bool gate = False;
9408
9409     if (isT) {
9410        if (INSNT0(15,4) == 0xFA8 && (INSNT1(15,0) & 0xF0F0) == 0xF020) {
9411           regN = INSNT0(3,0);
9412           regD = INSNT1(11,8);
9413           regM = INSNT1(3,0);
9414           if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
9415              gate = True;
9416        }
9417     } else {
9418        if (INSNA(27,20) == BITS8(0,1,1,0,0,0,1,1) &&
9419            INSNA(11,8)  == BITS4(1,1,1,1)         &&
9420            INSNA(7,4)   == BITS4(1,0,0,1)) {
9421           regD = INSNA(15,12);
9422           regN = INSNA(19,16);
9423           regM = INSNA(3,0);
9424           if (regD != 15 && regN != 15 && regM != 15)
9425              gate = True;
9426        }
9427     }
9428
9429     if (gate) {
9430        IRTemp rNt   = newTemp(Ity_I32);
9431        IRTemp rMt   = newTemp(Ity_I32);
9432        IRTemp res_q = newTemp(Ity_I32);
9433
9434        assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) );
9435        assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) );
9436
9437        assign(res_q, binop(Iop_HAdd8Sx4, mkexpr(rNt), mkexpr(rMt)));
9438        if (isT)
9439           putIRegT( regD, mkexpr(res_q), condT );
9440        else
9441           putIRegA( regD, mkexpr(res_q), condT, Ijk_Boring );
9442
9443        DIP("shadd8%s r%u, r%u, r%u\n", nCC(conq),regD,regN,regM);
9444        return True;
9445     }
9446     /* fall through */
9447   }
9448
9449   /* ------------------ qadd16<c> <Rd>,<Rn>,<Rm> ------------------ */
9450   {
9451     UInt regD = 99, regN = 99, regM = 99;
9452     Bool gate = False;
9453
9454     if (isT) {
9455        if (INSNT0(15,4) == 0xFA9 && (INSNT1(15,0) & 0xF0F0) == 0xF010) {
9456           regN = INSNT0(3,0);
9457           regD = INSNT1(11,8);
9458           regM = INSNT1(3,0);
9459           if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
9460              gate = True;
9461        }
9462     } else {
9463        if (INSNA(27,20) == BITS8(0,1,1,0,0,0,1,0) &&
9464            INSNA(11,8)  == BITS4(1,1,1,1)         &&
9465            INSNA(7,4)   == BITS4(0,0,0,1)) {
9466           regD = INSNA(15,12);
9467           regN = INSNA(19,16);
9468           regM = INSNA(3,0);
9469           if (regD != 15 && regN != 15 && regM != 15)
9470              gate = True;
9471        }
9472     }
9473
9474     if (gate) {
9475        IRTemp rNt   = newTemp(Ity_I32);
9476        IRTemp rMt   = newTemp(Ity_I32);
9477        IRTemp res_q = newTemp(Ity_I32);
9478
9479        assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) );
9480        assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) );
9481
9482        assign(res_q, binop(Iop_QAdd16Sx2, mkexpr(rNt), mkexpr(rMt)));
9483        if (isT)
9484           putIRegT( regD, mkexpr(res_q), condT );
9485        else
9486           putIRegA( regD, mkexpr(res_q), condT, Ijk_Boring );
9487
9488        DIP("qadd16%s r%u, r%u, r%u\n", nCC(conq),regD,regN,regM);
9489        return True;
9490     }
9491     /* fall through */
9492   }
9493
9494   /* ------------------ qsub16<c> <Rd>,<Rn>,<Rm> ------------------ */
9495   {
9496     UInt regD = 99, regN = 99, regM = 99;
9497     Bool gate = False;
9498
9499      if (isT) {
9500        if (INSNT0(15,4) == 0xFAD && (INSNT1(15,0) & 0xF0F0) == 0xF010) {
9501           regN = INSNT0(3,0);
9502           regD = INSNT1(11,8);
9503           regM = INSNT1(3,0);
9504           if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
9505              gate = True;
9506        }
9507     } else {
9508        if (INSNA(27,20) == BITS8(0,1,1,0,0,0,1,0) &&
9509            INSNA(11,8)  == BITS4(1,1,1,1)         &&
9510            INSNA(7,4)   == BITS4(0,1,1,1)) {
9511           regD = INSNA(15,12);
9512           regN = INSNA(19,16);
9513           regM = INSNA(3,0);
9514           if (regD != 15 && regN != 15 && regM != 15)
9515             gate = True;
9516        }
9517     }
9518
9519     if (gate) {
9520        IRTemp rNt   = newTemp(Ity_I32);
9521        IRTemp rMt   = newTemp(Ity_I32);
9522        IRTemp res_q = newTemp(Ity_I32);
9523
9524        assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) );
9525        assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) );
9526
9527        assign(res_q, binop(Iop_QSub16Sx2, mkexpr(rNt), mkexpr(rMt)));
9528        if (isT)
9529           putIRegT( regD, mkexpr(res_q), condT );
9530        else
9531           putIRegA( regD, mkexpr(res_q), condT, Ijk_Boring );
9532
9533        DIP("qsub16%s r%u, r%u, r%u\n", nCC(conq),regD,regN,regM);
9534        return True;
9535     }
9536     /* fall through */
9537   }
9538
9539   /////////////////////////////////////////////////////////////////
9540   /////////////////////////////////////////////////////////////////
9541   /////////////////////////////////////////////////////////////////
9542   /////////////////////////////////////////////////////////////////
9543   /////////////////////////////////////////////////////////////////
9544
9545   /* ------------------- qsax<c> <Rd>,<Rn>,<Rm> ------------------- */
9546   /* note: the hardware seems to construct the result differently
9547      from wot the manual says. */
9548   {
9549     UInt regD = 99, regN = 99, regM = 99;
9550     Bool gate = False;
9551
9552     if (isT) {
9553        if (INSNT0(15,4) == 0xFAE && (INSNT1(15,0) & 0xF0F0) == 0xF010) {
9554           regN = INSNT0(3,0);
9555           regD = INSNT1(11,8);
9556           regM = INSNT1(3,0);
9557           if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
9558              gate = True;
9559        }
9560     } else {
9561        if (INSNA(27,20) == BITS8(0,1,1,0,0,0,1,0) &&
9562            INSNA(11,8)  == BITS4(1,1,1,1)         &&
9563            INSNA(7,4)   == BITS4(0,1,0,1)) {
9564           regD = INSNA(15,12);
9565           regN = INSNA(19,16);
9566           regM = INSNA(3,0);
9567           if (regD != 15 && regN != 15 && regM != 15)
9568              gate = True;
9569        }
9570     }
9571
9572     if (gate) {
9573        IRTemp irt_regN     = newTemp(Ity_I32);
9574        IRTemp irt_regM     = newTemp(Ity_I32);
9575        IRTemp irt_sum      = newTemp(Ity_I32);
9576        IRTemp irt_diff     = newTemp(Ity_I32);
9577        IRTemp irt_sum_res  = newTemp(Ity_I32);
9578        IRTemp irt_diff_res = newTemp(Ity_I32);
9579
9580        assign( irt_regN, isT ? getIRegT(regN) : getIRegA(regN) );
9581        assign( irt_regM, isT ? getIRegT(regM) : getIRegA(regM) );
9582
9583        assign( irt_diff,
9584                binop( Iop_Sub32,
9585                       binop( Iop_Sar32, mkexpr(irt_regN), mkU8(16) ),
9586                       binop( Iop_Sar32,
9587                              binop(Iop_Shl32, mkexpr(irt_regM), mkU8(16)),
9588                              mkU8(16) ) ) );
9589        armSignedSatQ( irt_diff, 0x10, &irt_diff_res, NULL);
9590
9591        assign( irt_sum,
9592                binop( Iop_Add32,
9593                       binop( Iop_Sar32,
9594                              binop( Iop_Shl32, mkexpr(irt_regN), mkU8(16) ),
9595                              mkU8(16) ),
9596                       binop( Iop_Sar32, mkexpr(irt_regM), mkU8(16) )) );
9597        armSignedSatQ( irt_sum, 0x10, &irt_sum_res, NULL );
9598
9599        IRExpr* ire_result = binop( Iop_Or32,
9600                                    binop( Iop_Shl32, mkexpr(irt_diff_res),
9601                                           mkU8(16) ),
9602                                    binop( Iop_And32, mkexpr(irt_sum_res),
9603                                           mkU32(0xFFFF)) );
9604
9605        if (isT)
9606           putIRegT( regD, ire_result, condT );
9607        else
9608           putIRegA( regD, ire_result, condT, Ijk_Boring );
9609
9610        DIP( "qsax%s r%u, r%u, r%u\n", nCC(conq), regD, regN, regM );
9611        return True;
9612     }
9613     /* fall through */
9614   }
9615
9616   /* ------------------- qasx<c> <Rd>,<Rn>,<Rm> ------------------- */
9617   {
9618     UInt regD = 99, regN = 99, regM = 99;
9619     Bool gate = False;
9620
9621     if (isT) {
9622        if (INSNT0(15,4) == 0xFAA && (INSNT1(15,0) & 0xF0F0) == 0xF010) {
9623           regN = INSNT0(3,0);
9624           regD = INSNT1(11,8);
9625           regM = INSNT1(3,0);
9626           if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
9627              gate = True;
9628        }
9629     } else {
9630        if (INSNA(27,20) == BITS8(0,1,1,0,0,0,1,0) &&
9631            INSNA(11,8)  == BITS4(1,1,1,1)         &&
9632            INSNA(7,4)   == BITS4(0,0,1,1)) {
9633           regD = INSNA(15,12);
9634           regN = INSNA(19,16);
9635           regM = INSNA(3,0);
9636           if (regD != 15 && regN != 15 && regM != 15)
9637              gate = True;
9638        }
9639     }
9640
9641     if (gate) {
9642        IRTemp irt_regN     = newTemp(Ity_I32);
9643        IRTemp irt_regM     = newTemp(Ity_I32);
9644        IRTemp irt_sum      = newTemp(Ity_I32);
9645        IRTemp irt_diff     = newTemp(Ity_I32);
9646        IRTemp irt_res_sum  = newTemp(Ity_I32);
9647        IRTemp irt_res_diff = newTemp(Ity_I32);
9648
9649        assign( irt_regN, isT ? getIRegT(regN) : getIRegA(regN) );
9650        assign( irt_regM, isT ? getIRegT(regM) : getIRegA(regM) );
9651
9652        assign( irt_diff,
9653                binop( Iop_Sub32,
9654                       binop( Iop_Sar32,
9655                              binop( Iop_Shl32, mkexpr(irt_regN), mkU8(16) ),
9656                              mkU8(16) ),
9657                       binop( Iop_Sar32, mkexpr(irt_regM), mkU8(16) ) ) );
9658        armSignedSatQ( irt_diff, 0x10, &irt_res_diff, NULL );
9659
9660        assign( irt_sum,
9661                binop( Iop_Add32,
9662                       binop( Iop_Sar32, mkexpr(irt_regN), mkU8(16) ),
9663                       binop( Iop_Sar32,
9664                              binop( Iop_Shl32, mkexpr(irt_regM), mkU8(16) ),
9665                              mkU8(16) ) ) );
9666        armSignedSatQ( irt_sum, 0x10, &irt_res_sum, NULL );
9667
9668        IRExpr* ire_result
9669          = binop( Iop_Or32,
9670                   binop( Iop_Shl32, mkexpr(irt_res_sum), mkU8(16) ),
9671                   binop( Iop_And32, mkexpr(irt_res_diff), mkU32(0xFFFF) ) );
9672
9673        if (isT)
9674           putIRegT( regD, ire_result, condT );
9675        else
9676           putIRegA( regD, ire_result, condT, Ijk_Boring );
9677
9678        DIP( "qasx%s r%u, r%u, r%u\n", nCC(conq), regD, regN, regM );
9679        return True;
9680     }
9681     /* fall through */
9682   }
9683
9684   /* ------------------- sasx<c> <Rd>,<Rn>,<Rm> ------------------- */
9685   {
9686     UInt regD = 99, regN = 99, regM = 99;
9687     Bool gate = False;
9688
9689     if (isT) {
9690        if (INSNT0(15,4) == 0xFAA && (INSNT1(15,0) & 0xF0F0) == 0xF000) {
9691           regN = INSNT0(3,0);
9692           regD = INSNT1(11,8);
9693           regM = INSNT1(3,0);
9694           if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
9695              gate = True;
9696        }
9697     } else {
9698        if (INSNA(27,20) == BITS8(0,1,1,0,0,0,0,1) &&
9699            INSNA(11,8)  == BITS4(1,1,1,1)         &&
9700            INSNA(7,4)   == BITS4(0,0,1,1)) {
9701           regD = INSNA(15,12);
9702           regN = INSNA(19,16);
9703           regM = INSNA(3,0);
9704           if (regD != 15 && regN != 15 && regM != 15)
9705              gate = True;
9706        }
9707     }
9708
9709     if (gate) {
9710        IRTemp irt_regN = newTemp(Ity_I32);
9711        IRTemp irt_regM = newTemp(Ity_I32);
9712        IRTemp irt_sum  = newTemp(Ity_I32);
9713        IRTemp irt_diff = newTemp(Ity_I32);
9714
9715        assign( irt_regN, isT ? getIRegT(regN) : getIRegA(regN) );
9716        assign( irt_regM, isT ? getIRegT(regM) : getIRegA(regM) );
9717
9718        assign( irt_diff,
9719                binop( Iop_Sub32,
9720                       binop( Iop_Sar32,
9721                              binop( Iop_Shl32, mkexpr(irt_regN), mkU8(16) ),
9722                              mkU8(16) ),
9723                       binop( Iop_Sar32, mkexpr(irt_regM), mkU8(16) ) ) );
9724
9725        assign( irt_sum,
9726                binop( Iop_Add32,
9727                       binop( Iop_Sar32, mkexpr(irt_regN), mkU8(16) ),
9728                       binop( Iop_Sar32,
9729                              binop( Iop_Shl32, mkexpr(irt_regM), mkU8(16) ),
9730                              mkU8(16) ) ) );
9731
9732        IRExpr* ire_result
9733          = binop( Iop_Or32,
9734                   binop( Iop_Shl32, mkexpr(irt_sum), mkU8(16) ),
9735                   binop( Iop_And32, mkexpr(irt_diff), mkU32(0xFFFF) ) );
9736
9737        IRTemp ge10 = newTemp(Ity_I32);
9738        assign(ge10, unop(Iop_Not32, mkexpr(irt_diff)));
9739        put_GEFLAG32( 0, 31, mkexpr(ge10), condT );
9740        put_GEFLAG32( 1, 31, mkexpr(ge10), condT );
9741
9742        IRTemp ge32 = newTemp(Ity_I32);
9743        assign(ge32, unop(Iop_Not32, mkexpr(irt_sum)));
9744        put_GEFLAG32( 2, 31, mkexpr(ge32), condT );
9745        put_GEFLAG32( 3, 31, mkexpr(ge32), condT );
9746
9747        if (isT)
9748           putIRegT( regD, ire_result, condT );
9749        else
9750           putIRegA( regD, ire_result, condT, Ijk_Boring );
9751
9752        DIP( "sasx%s r%u, r%u, r%u\n", nCC(conq), regD, regN, regM );
9753        return True;
9754     }
9755     /* fall through */
9756   }
9757
9758   /* --------------- smuad, smuadx<c><Rd>,<Rn>,<Rm> --------------- */
9759   /* --------------- smsad, smsadx<c><Rd>,<Rn>,<Rm> --------------- */
9760   {
9761     UInt regD = 99, regN = 99, regM = 99, bitM = 99;
9762     Bool gate = False, isAD = False;
9763
9764     if (isT) {
9765        if ((INSNT0(15,4) == 0xFB2 || INSNT0(15,4) == 0xFB4)
9766            && (INSNT1(15,0) & 0xF0E0) == 0xF000) {
9767           regN = INSNT0(3,0);
9768           regD = INSNT1(11,8);
9769           regM = INSNT1(3,0);
9770           bitM = INSNT1(4,4);
9771           isAD = INSNT0(15,4) == 0xFB2;
9772           if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
9773              gate = True;
9774        }
9775     } else {
9776        if (INSNA(27,20) == BITS8(0,1,1,1,0,0,0,0) &&
9777            INSNA(15,12) == BITS4(1,1,1,1)         &&
9778            (INSNA(7,4) & BITS4(1,0,0,1)) == BITS4(0,0,0,1) ) {
9779           regD = INSNA(19,16);
9780           regN = INSNA(3,0);
9781           regM = INSNA(11,8);
9782           bitM = INSNA(5,5);
9783           isAD = INSNA(6,6) == 0;
9784           if (regD != 15 && regN != 15 && regM != 15)
9785              gate = True;
9786        }
9787     }
9788
9789     if (gate) {
9790        IRTemp irt_regN    = newTemp(Ity_I32);
9791        IRTemp irt_regM    = newTemp(Ity_I32);
9792        IRTemp irt_prod_lo = newTemp(Ity_I32);
9793        IRTemp irt_prod_hi = newTemp(Ity_I32);
9794        IRTemp tmpM        = newTemp(Ity_I32);
9795
9796        assign( irt_regN, isT ? getIRegT(regN) : getIRegA(regN) );
9797
9798        assign( tmpM, isT ? getIRegT(regM) : getIRegA(regM) );
9799        assign( irt_regM, genROR32(tmpM, (bitM & 1) ? 16 : 0) );
9800
9801        assign( irt_prod_lo,
9802                binop( Iop_Mul32,
9803                       binop( Iop_Sar32,
9804                              binop(Iop_Shl32, mkexpr(irt_regN), mkU8(16)),
9805                              mkU8(16) ),
9806                       binop( Iop_Sar32,
9807                              binop(Iop_Shl32, mkexpr(irt_regM), mkU8(16)),
9808                              mkU8(16) ) ) );
9809        assign( irt_prod_hi, binop(Iop_Mul32,
9810                                   binop(Iop_Sar32, mkexpr(irt_regN), mkU8(16)),
9811                                   binop(Iop_Sar32, mkexpr(irt_regM), mkU8(16))) );
9812        IRExpr* ire_result
9813           = binop( isAD ? Iop_Add32 : Iop_Sub32,
9814                    mkexpr(irt_prod_lo), mkexpr(irt_prod_hi) );
9815
9816        if (isT)
9817           putIRegT( regD, ire_result, condT );
9818        else
9819           putIRegA( regD, ire_result, condT, Ijk_Boring );
9820
9821        if (isAD) {
9822           or_into_QFLAG32(
9823              signed_overflow_after_Add32( ire_result,
9824                                           irt_prod_lo, irt_prod_hi ),
9825              condT
9826           );
9827        }
9828
9829        DIP("smu%cd%s%s r%u, r%u, r%u\n",
9830            isAD ? 'a' : 's',
9831            bitM ? "x" : "", nCC(conq), regD, regN, regM);
9832        return True;
9833     }
9834     /* fall through */
9835   }
9836
9837   /* --------------- smlad{X}<c> <Rd>,<Rn>,<Rm>,<Ra> -------------- */
9838   /* --------------- smlsd{X}<c> <Rd>,<Rn>,<Rm>,<Ra> -------------- */
9839   {
9840     UInt regD = 99, regN = 99, regM = 99, regA = 99, bitM = 99;
9841     Bool gate = False, isAD = False;
9842
9843     if (isT) {
9844       if ((INSNT0(15,4) == 0xFB2 || INSNT0(15,4) == 0xFB4)
9845           && INSNT1(7,5) == BITS3(0,0,0)) {
9846           regN = INSNT0(3,0);
9847           regD = INSNT1(11,8);
9848           regM = INSNT1(3,0);
9849           regA = INSNT1(15,12);
9850           bitM = INSNT1(4,4);
9851           isAD = INSNT0(15,4) == 0xFB2;
9852           if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM)
9853               && !isBadRegT(regA))
9854              gate = True;
9855        }
9856     } else {
9857        if (INSNA(27,20) == BITS8(0,1,1,1,0,0,0,0) &&
9858            (INSNA(7,4) & BITS4(1,0,0,1)) == BITS4(0,0,0,1)) {
9859           regD = INSNA(19,16);
9860           regA = INSNA(15,12);
9861           regN = INSNA(3,0);
9862           regM = INSNA(11,8);
9863           bitM = INSNA(5,5);
9864           isAD = INSNA(6,6) == 0;
9865           if (regD != 15 && regN != 15 && regM != 15 && regA != 15)
9866              gate = True;
9867        }
9868     }
9869
9870     if (gate) {
9871        IRTemp irt_regN    = newTemp(Ity_I32);
9872        IRTemp irt_regM    = newTemp(Ity_I32);
9873        IRTemp irt_regA    = newTemp(Ity_I32);
9874        IRTemp irt_prod_lo = newTemp(Ity_I32);
9875        IRTemp irt_prod_hi = newTemp(Ity_I32);
9876        IRTemp irt_sum     = newTemp(Ity_I32);
9877        IRTemp tmpM        = newTemp(Ity_I32);
9878
9879        assign( irt_regN, isT ? getIRegT(regN) : getIRegA(regN) );
9880        assign( irt_regA, isT ? getIRegT(regA) : getIRegA(regA) );
9881
9882        assign( tmpM, isT ? getIRegT(regM) : getIRegA(regM) );
9883        assign( irt_regM, genROR32(tmpM, (bitM & 1) ? 16 : 0) );
9884
9885        assign( irt_prod_lo,
9886                binop(Iop_Mul32,
9887                      binop(Iop_Sar32,
9888                            binop( Iop_Shl32, mkexpr(irt_regN), mkU8(16) ),
9889                            mkU8(16)),
9890                      binop(Iop_Sar32,
9891                            binop( Iop_Shl32, mkexpr(irt_regM), mkU8(16) ),
9892                            mkU8(16))) );
9893        assign( irt_prod_hi,
9894                binop( Iop_Mul32,
9895                       binop( Iop_Sar32, mkexpr(irt_regN), mkU8(16) ),
9896                       binop( Iop_Sar32, mkexpr(irt_regM), mkU8(16) ) ) );
9897        assign( irt_sum, binop( isAD ? Iop_Add32 : Iop_Sub32,
9898                                mkexpr(irt_prod_lo), mkexpr(irt_prod_hi) ) );
9899
9900        IRExpr* ire_result = binop(Iop_Add32, mkexpr(irt_sum), mkexpr(irt_regA));
9901
9902        if (isT)
9903           putIRegT( regD, ire_result, condT );
9904        else
9905           putIRegA( regD, ire_result, condT, Ijk_Boring );
9906
9907        if (isAD) {
9908           or_into_QFLAG32(
9909              signed_overflow_after_Add32( mkexpr(irt_sum),
9910                                           irt_prod_lo, irt_prod_hi ),
9911              condT
9912           );
9913        }
9914
9915        or_into_QFLAG32(
9916           signed_overflow_after_Add32( ire_result, irt_sum, irt_regA ),
9917           condT
9918        );
9919
9920        DIP("sml%cd%s%s r%u, r%u, r%u, r%u\n",
9921            isAD ? 'a' : 's',
9922            bitM ? "x" : "", nCC(conq), regD, regN, regM, regA);
9923        return True;
9924     }
9925     /* fall through */
9926   }
9927
9928   /* ----- smlabb, smlabt, smlatb, smlatt <Rd>,<Rn>,<Rm>,<Ra> ----- */
9929   {
9930     UInt regD = 99, regN = 99, regM = 99, regA = 99, bitM = 99, bitN = 99;
9931     Bool gate = False;
9932
9933     if (isT) {
9934        if (INSNT0(15,4) == 0xFB1 && INSNT1(7,6) == BITS2(0,0)) {
9935           regN = INSNT0(3,0);
9936           regD = INSNT1(11,8);
9937           regM = INSNT1(3,0);
9938           regA = INSNT1(15,12);
9939           bitM = INSNT1(4,4);
9940           bitN = INSNT1(5,5);
9941           if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM)
9942               && !isBadRegT(regA))
9943              gate = True;
9944        }
9945     } else {
9946        if (INSNA(27,20) == BITS8(0,0,0,1,0,0,0,0) &&
9947            (INSNA(7,4) & BITS4(1,0,0,1)) == BITS4(1,0,0,0)) {
9948           regD = INSNA(19,16);
9949           regN = INSNA(3,0);
9950           regM = INSNA(11,8);
9951           regA = INSNA(15,12);
9952           bitM = INSNA(6,6);
9953           bitN = INSNA(5,5);
9954           if (regD != 15 && regN != 15 && regM != 15 && regA != 15)
9955              gate = True;
9956        }
9957     }
9958
9959     if (gate) {
9960        IRTemp irt_regA = newTemp(Ity_I32);
9961        IRTemp irt_prod = newTemp(Ity_I32);
9962
9963        assign( irt_prod,
9964                binop(Iop_Mul32,
9965                      binop(Iop_Sar32,
9966                            binop(Iop_Shl32,
9967                                  isT ? getIRegT(regN) : getIRegA(regN),
9968                                  mkU8(bitN ? 0 : 16)),
9969                            mkU8(16)),
9970                      binop(Iop_Sar32,
9971                            binop(Iop_Shl32,
9972                                  isT ? getIRegT(regM) : getIRegA(regM),
9973                                  mkU8(bitM ? 0 : 16)),
9974                            mkU8(16))) );
9975
9976        assign( irt_regA, isT ? getIRegT(regA) : getIRegA(regA) );
9977
9978        IRExpr* ire_result = binop(Iop_Add32, mkexpr(irt_prod), mkexpr(irt_regA));
9979
9980        if (isT)
9981           putIRegT( regD, ire_result, condT );
9982        else
9983           putIRegA( regD, ire_result, condT, Ijk_Boring );
9984
9985        or_into_QFLAG32(
9986           signed_overflow_after_Add32( ire_result, irt_prod, irt_regA ),
9987           condT
9988        );
9989
9990        DIP( "smla%c%c%s r%u, r%u, r%u, r%u\n",
9991             bitN ? 't' : 'b', bitM ? 't' : 'b',
9992             nCC(conq), regD, regN, regM, regA );
9993        return True;
9994     }
9995     /* fall through */
9996   }
9997
9998   /* ----- smlawb, smlawt <Rd>,<Rn>,<Rm>,<Ra> ----- */
9999   {
10000     UInt regD = 99, regN = 99, regM = 99, regA = 99, bitM = 99;
10001     Bool gate = False;
10002
10003     if (isT) {
10004        if (INSNT0(15,4) == 0xFB3 && INSNT1(7,5) == BITS3(0,0,0)) {
10005           regN = INSNT0(3,0);
10006           regD = INSNT1(11,8);
10007           regM = INSNT1(3,0);
10008           regA = INSNT1(15,12);
10009           bitM = INSNT1(4,4);
10010           if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM)
10011               && !isBadRegT(regA))
10012              gate = True;
10013        }
10014     } else {
10015        if (INSNA(27,20) == BITS8(0,0,0,1,0,0,1,0) &&
10016            (INSNA(7,4) & BITS4(1,0,1,1)) == BITS4(1,0,0,0)) {
10017           regD = INSNA(19,16);
10018           regN = INSNA(3,0);
10019           regM = INSNA(11,8);
10020           regA = INSNA(15,12);
10021           bitM = INSNA(6,6);
10022           if (regD != 15 && regN != 15 && regM != 15 && regA != 15)
10023              gate = True;
10024        }
10025     }
10026
10027     if (gate) {
10028        IRTemp irt_regA = newTemp(Ity_I32);
10029        IRTemp irt_prod = newTemp(Ity_I64);
10030
10031        assign( irt_prod,
10032                binop(Iop_MullS32,
10033                      isT ? getIRegT(regN) : getIRegA(regN),
10034                      binop(Iop_Sar32,
10035                            binop(Iop_Shl32,
10036                                  isT ? getIRegT(regM) : getIRegA(regM),
10037                                  mkU8(bitM ? 0 : 16)),
10038                            mkU8(16))) );
10039
10040        assign( irt_regA, isT ? getIRegT(regA) : getIRegA(regA) );
10041
10042        IRTemp prod32 = newTemp(Ity_I32);
10043        assign(prod32,
10044               binop(Iop_Or32,
10045                     binop(Iop_Shl32, unop(Iop_64HIto32, mkexpr(irt_prod)), mkU8(16)),
10046                     binop(Iop_Shr32, unop(Iop_64to32, mkexpr(irt_prod)), mkU8(16))
10047        ));
10048
10049        IRExpr* ire_result = binop(Iop_Add32, mkexpr(prod32), mkexpr(irt_regA));
10050
10051        if (isT)
10052           putIRegT( regD, ire_result, condT );
10053        else
10054           putIRegA( regD, ire_result, condT, Ijk_Boring );
10055
10056        or_into_QFLAG32(
10057           signed_overflow_after_Add32( ire_result, prod32, irt_regA ),
10058           condT
10059        );
10060
10061        DIP( "smlaw%c%s r%u, r%u, r%u, r%u\n",
10062             bitM ? 't' : 'b',
10063             nCC(conq), regD, regN, regM, regA );
10064        return True;
10065     }
10066     /* fall through */
10067   }
10068
10069   /* ------------------- sel<c> <Rd>,<Rn>,<Rm> -------------------- */
10070   /* fixme: fix up the test in v6media.c so that we can pass the ge
10071      flags as part of the test. */
10072   {
10073     UInt regD = 99, regN = 99, regM = 99;
10074     Bool gate = False;
10075
10076     if (isT) {
10077        if (INSNT0(15,4) == 0xFAA && (INSNT1(15,0) & 0xF0F0) == 0xF080) {
10078           regN = INSNT0(3,0);
10079           regD = INSNT1(11,8);
10080           regM = INSNT1(3,0);
10081           if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
10082              gate = True;
10083        }
10084     } else {
10085        if (INSNA(27,20) == BITS8(0,1,1,0,1,0,0,0) &&
10086            INSNA(11,8)  == BITS4(1,1,1,1)         &&
10087            INSNA(7,4)   == BITS4(1,0,1,1)) {
10088           regD = INSNA(15,12);
10089           regN = INSNA(19,16);
10090           regM = INSNA(3,0);
10091           if (regD != 15 && regN != 15 && regM != 15)
10092              gate = True;
10093        }
10094     }
10095
10096     if (gate) {
10097        IRTemp irt_ge_flag0 = newTemp(Ity_I32);
10098        IRTemp irt_ge_flag1 = newTemp(Ity_I32);
10099        IRTemp irt_ge_flag2 = newTemp(Ity_I32);
10100        IRTemp irt_ge_flag3 = newTemp(Ity_I32);
10101
10102        assign( irt_ge_flag0, get_GEFLAG32(0) );
10103        assign( irt_ge_flag1, get_GEFLAG32(1) );
10104        assign( irt_ge_flag2, get_GEFLAG32(2) );
10105        assign( irt_ge_flag3, get_GEFLAG32(3) );
10106
10107        IRExpr* ire_ge_flag0_or
10108          = binop(Iop_Or32, mkexpr(irt_ge_flag0),
10109                  binop(Iop_Sub32, mkU32(0), mkexpr(irt_ge_flag0)));
10110        IRExpr* ire_ge_flag1_or
10111          = binop(Iop_Or32, mkexpr(irt_ge_flag1),
10112                  binop(Iop_Sub32, mkU32(0), mkexpr(irt_ge_flag1)));
10113        IRExpr* ire_ge_flag2_or
10114          = binop(Iop_Or32, mkexpr(irt_ge_flag2),
10115                  binop(Iop_Sub32, mkU32(0), mkexpr(irt_ge_flag2)));
10116        IRExpr* ire_ge_flag3_or
10117          = binop(Iop_Or32, mkexpr(irt_ge_flag3),
10118                  binop(Iop_Sub32, mkU32(0), mkexpr(irt_ge_flag3)));
10119
10120        IRExpr* ire_ge_flags
10121          = binop( Iop_Or32,
10122                   binop(Iop_Or32,
10123                         binop(Iop_And32,
10124                               binop(Iop_Sar32, ire_ge_flag0_or, mkU8(31)),
10125                               mkU32(0x000000ff)),
10126                         binop(Iop_And32,
10127                               binop(Iop_Sar32, ire_ge_flag1_or, mkU8(31)),
10128                               mkU32(0x0000ff00))),
10129                   binop(Iop_Or32,
10130                         binop(Iop_And32,
10131                               binop(Iop_Sar32, ire_ge_flag2_or, mkU8(31)),
10132                               mkU32(0x00ff0000)),
10133                         binop(Iop_And32,
10134                               binop(Iop_Sar32, ire_ge_flag3_or, mkU8(31)),
10135                               mkU32(0xff000000))) );
10136
10137        IRExpr* ire_result
10138          = binop(Iop_Or32,
10139                  binop(Iop_And32,
10140                        isT ? getIRegT(regN) : getIRegA(regN),
10141                        ire_ge_flags ),
10142                  binop(Iop_And32,
10143                        isT ? getIRegT(regM) : getIRegA(regM),
10144                        unop(Iop_Not32, ire_ge_flags)));
10145
10146        if (isT)
10147           putIRegT( regD, ire_result, condT );
10148        else
10149           putIRegA( regD, ire_result, condT, Ijk_Boring );
10150
10151        DIP("sel%s r%u, r%u, r%u\n", nCC(conq), regD, regN, regM );
10152        return True;
10153     }
10154     /* fall through */
10155   }
10156
10157   /* ----------------- uxtab16<c> Rd,Rn,Rm{,rot} ------------------ */
10158   {
10159     UInt regD = 99, regN = 99, regM = 99, rotate = 99;
10160     Bool gate = False;
10161
10162     if (isT) {
10163        if (INSNT0(15,4) == 0xFA3 && (INSNT1(15,0) & 0xF0C0) == 0xF080) {
10164           regN   = INSNT0(3,0);
10165           regD   = INSNT1(11,8);
10166           regM   = INSNT1(3,0);
10167           rotate = INSNT1(5,4);
10168           if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
10169              gate = True;
10170        }
10171     } else {
10172        if (INSNA(27,20) == BITS8(0,1,1,0,1,1,0,0) &&
10173            INSNA(9,4)   == BITS6(0,0,0,1,1,1) ) {
10174           regD   = INSNA(15,12);
10175           regN   = INSNA(19,16);
10176           regM   = INSNA(3,0);
10177           rotate = INSNA(11,10);
10178           if (regD != 15 && regN != 15 && regM != 15)
10179             gate = True;
10180        }
10181     }
10182
10183     if (gate) {
10184        IRTemp irt_regN = newTemp(Ity_I32);
10185        assign( irt_regN, isT ? getIRegT(regN) : getIRegA(regN) );
10186
10187        IRTemp irt_regM = newTemp(Ity_I32);
10188        assign( irt_regM, isT ? getIRegT(regM) : getIRegA(regM) );
10189
10190        IRTemp irt_rot = newTemp(Ity_I32);
10191        assign( irt_rot, binop(Iop_And32,
10192                               genROR32(irt_regM, 8 * rotate),
10193                               mkU32(0x00FF00FF)) );
10194
10195        IRExpr* resLo
10196           = binop(Iop_And32,
10197                   binop(Iop_Add32, mkexpr(irt_regN), mkexpr(irt_rot)),
10198                   mkU32(0x0000FFFF));
10199
10200        IRExpr* resHi
10201           = binop(Iop_Add32,
10202                   binop(Iop_And32, mkexpr(irt_regN), mkU32(0xFFFF0000)),
10203                   binop(Iop_And32, mkexpr(irt_rot),  mkU32(0xFFFF0000)));
10204
10205        IRExpr* ire_result
10206           = binop( Iop_Or32, resHi, resLo );
10207
10208        if (isT)
10209           putIRegT( regD, ire_result, condT );
10210        else
10211           putIRegA( regD, ire_result, condT, Ijk_Boring );
10212
10213        DIP( "uxtab16%s r%u, r%u, r%u, ROR #%u\n",
10214             nCC(conq), regD, regN, regM, 8 * rotate );
10215        return True;
10216     }
10217     /* fall through */
10218   }
10219
10220   /* --------------- usad8  Rd,Rn,Rm    ---------------- */
10221   /* --------------- usada8 Rd,Rn,Rm,Ra ---------------- */
10222   {
10223     UInt rD = 99, rN = 99, rM = 99, rA = 99;
10224     Bool gate = False;
10225
10226     if (isT) {
10227       if (INSNT0(15,4) == 0xFB7 && INSNT1(7,4) == BITS4(0,0,0,0)) {
10228           rN = INSNT0(3,0);
10229           rA = INSNT1(15,12);
10230           rD = INSNT1(11,8);
10231           rM = INSNT1(3,0);
10232           if (!isBadRegT(rD) && !isBadRegT(rN) && !isBadRegT(rM) && rA != 13)
10233              gate = True;
10234        }
10235     } else {
10236        if (INSNA(27,20) == BITS8(0,1,1,1,1,0,0,0) &&
10237            INSNA(7,4)   == BITS4(0,0,0,1) ) {
10238           rD = INSNA(19,16);
10239           rA = INSNA(15,12);
10240           rM = INSNA(11,8);
10241           rN = INSNA(3,0);
10242           if (rD != 15 && rN != 15 && rM != 15 /* but rA can be 15 */)
10243              gate = True;
10244        }
10245     }
10246     /* We allow rA == 15, to denote the usad8 (no accumulator) case. */
10247
10248     if (gate) {
10249        IRExpr* rNe = isT ? getIRegT(rN) : getIRegA(rN);
10250        IRExpr* rMe = isT ? getIRegT(rM) : getIRegA(rM);
10251        IRExpr* rAe = rA == 15 ? mkU32(0)
10252                               : (isT ? getIRegT(rA) : getIRegA(rA));
10253        IRExpr* res = binop(Iop_Add32,
10254                            binop(Iop_Sad8Ux4, rNe, rMe),
10255                            rAe);
10256        if (isT)
10257           putIRegT( rD, res, condT );
10258        else
10259           putIRegA( rD, res, condT, Ijk_Boring );
10260
10261        if (rA == 15) {
10262           DIP( "usad8%s r%u, r%u, r%u\n",
10263                nCC(conq), rD, rN, rM );
10264        } else {
10265           DIP( "usada8%s r%u, r%u, r%u, r%u\n",
10266                nCC(conq), rD, rN, rM, rA );
10267        }
10268        return True;
10269     }
10270     /* fall through */
10271   }
10272
10273   /* ------------------ qadd<c> <Rd>,<Rn>,<Rm> ------------------- */
10274   {
10275     UInt regD = 99, regN = 99, regM = 99;
10276     Bool gate = False;
10277
10278     if (isT) {
10279        if (INSNT0(15,4) == 0xFA8 && (INSNT1(15,0) & 0xF0F0) == 0xF080) {
10280           regN = INSNT0(3,0);
10281           regD = INSNT1(11,8);
10282           regM = INSNT1(3,0);
10283           if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
10284              gate = True;
10285        }
10286     } else {
10287        if (INSNA(27,20) == BITS8(0,0,0,1,0,0,0,0) &&
10288            INSNA(11,8)  == BITS4(0,0,0,0)         &&
10289            INSNA(7,4)   == BITS4(0,1,0,1)) {
10290           regD = INSNA(15,12);
10291           regN = INSNA(19,16);
10292           regM = INSNA(3,0);
10293           if (regD != 15 && regN != 15 && regM != 15)
10294              gate = True;
10295        }
10296     }
10297
10298     if (gate) {
10299        IRTemp rNt   = newTemp(Ity_I32);
10300        IRTemp rMt   = newTemp(Ity_I32);
10301        IRTemp res_q = newTemp(Ity_I32);
10302
10303        assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) );
10304        assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) );
10305
10306        assign(res_q, binop(Iop_QAdd32S, mkexpr(rMt), mkexpr(rNt)));
10307        if (isT)
10308           putIRegT( regD, mkexpr(res_q), condT );
10309        else
10310           putIRegA( regD, mkexpr(res_q), condT, Ijk_Boring );
10311
10312        or_into_QFLAG32(
10313           signed_overflow_after_Add32(
10314              binop(Iop_Add32, mkexpr(rMt), mkexpr(rNt)), rMt, rNt),
10315           condT
10316        );
10317
10318        DIP("qadd%s r%u, r%u, r%u\n", nCC(conq),regD,regM,regN);
10319        return True;
10320     }
10321     /* fall through */
10322   }
10323
10324   /* ------------------ qdadd<c> <Rd>,<Rm>,<Rn> ------------------- */
10325   {
10326     UInt regD = 99, regN = 99, regM = 99;
10327     Bool gate = False;
10328
10329     if (isT) {
10330        if (INSNT0(15,4) == 0xFA8 && (INSNT1(15,0) & 0xF0F0) == 0xF090) {
10331           regN = INSNT0(3,0);
10332           regD = INSNT1(11,8);
10333           regM = INSNT1(3,0);
10334           if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
10335              gate = True;
10336        }
10337     } else {
10338        if (INSNA(27,20) == BITS8(0,0,0,1,0,1,0,0) &&
10339            INSNA(11,8)  == BITS4(0,0,0,0)         &&
10340            INSNA(7,4)   == BITS4(0,1,0,1)) {
10341           regD = INSNA(15,12);
10342           regN = INSNA(19,16);
10343           regM = INSNA(3,0);
10344           if (regD != 15 && regN != 15 && regM != 15)
10345              gate = True;
10346        }
10347     }
10348
10349     if (gate) {
10350        IRTemp rNt   = newTemp(Ity_I32);
10351        IRTemp rMt   = newTemp(Ity_I32);
10352        IRTemp rN_d  = newTemp(Ity_I32);
10353        IRTemp res_q = newTemp(Ity_I32);
10354
10355        assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) );
10356        assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) );
10357
10358        or_into_QFLAG32(
10359           signed_overflow_after_Add32(
10360              binop(Iop_Add32, mkexpr(rNt), mkexpr(rNt)), rNt, rNt),
10361           condT
10362        );
10363
10364        assign(rN_d,  binop(Iop_QAdd32S, mkexpr(rNt), mkexpr(rNt)));
10365        assign(res_q, binop(Iop_QAdd32S, mkexpr(rMt), mkexpr(rN_d)));
10366        if (isT)
10367           putIRegT( regD, mkexpr(res_q), condT );
10368        else
10369           putIRegA( regD, mkexpr(res_q), condT, Ijk_Boring );
10370
10371        or_into_QFLAG32(
10372           signed_overflow_after_Add32(
10373              binop(Iop_Add32, mkexpr(rMt), mkexpr(rN_d)), rMt, rN_d),
10374           condT
10375        );
10376
10377        DIP("qdadd%s r%u, r%u, r%u\n", nCC(conq),regD,regM,regN);
10378        return True;
10379     }
10380     /* fall through */
10381   }
10382
10383   /* ------------------ qsub<c> <Rd>,<Rn>,<Rm> ------------------- */
10384   {
10385     UInt regD = 99, regN = 99, regM = 99;
10386     Bool gate = False;
10387
10388     if (isT) {
10389        if (INSNT0(15,4) == 0xFA8 && (INSNT1(15,0) & 0xF0F0) == 0xF0A0) {
10390           regN = INSNT0(3,0);
10391           regD = INSNT1(11,8);
10392           regM = INSNT1(3,0);
10393           if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
10394              gate = True;
10395        }
10396     } else {
10397        if (INSNA(27,20) == BITS8(0,0,0,1,0,0,1,0) &&
10398            INSNA(11,8)  == BITS4(0,0,0,0)         &&
10399            INSNA(7,4)   == BITS4(0,1,0,1)) {
10400           regD = INSNA(15,12);
10401           regN = INSNA(19,16);
10402           regM = INSNA(3,0);
10403           if (regD != 15 && regN != 15 && regM != 15)
10404              gate = True;
10405        }
10406     }
10407
10408     if (gate) {
10409        IRTemp rNt   = newTemp(Ity_I32);
10410        IRTemp rMt   = newTemp(Ity_I32);
10411        IRTemp res_q = newTemp(Ity_I32);
10412
10413        assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) );
10414        assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) );
10415
10416        assign(res_q, binop(Iop_QSub32S, mkexpr(rMt), mkexpr(rNt)));
10417        if (isT)
10418           putIRegT( regD, mkexpr(res_q), condT );
10419        else
10420           putIRegA( regD, mkexpr(res_q), condT, Ijk_Boring );
10421
10422        or_into_QFLAG32(
10423           signed_overflow_after_Sub32(
10424              binop(Iop_Sub32, mkexpr(rMt), mkexpr(rNt)), rMt, rNt),
10425           condT
10426        );
10427
10428        DIP("qsub%s r%u, r%u, r%u\n", nCC(conq),regD,regM,regN);
10429        return True;
10430     }
10431     /* fall through */
10432   }
10433
10434   /* ------------------ qdsub<c> <Rd>,<Rm>,<Rn> ------------------- */
10435   {
10436     UInt regD = 99, regN = 99, regM = 99;
10437     Bool gate = False;
10438
10439     if (isT) {
10440        if (INSNT0(15,4) == 0xFA8 && (INSNT1(15,0) & 0xF0F0) == 0xF0B0) {
10441           regN = INSNT0(3,0);
10442           regD = INSNT1(11,8);
10443           regM = INSNT1(3,0);
10444           if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
10445              gate = True;
10446        }
10447     } else {
10448        if (INSNA(27,20) == BITS8(0,0,0,1,0,1,1,0) &&
10449            INSNA(11,8)  == BITS4(0,0,0,0)         &&
10450            INSNA(7,4)   == BITS4(0,1,0,1)) {
10451           regD = INSNA(15,12);
10452           regN = INSNA(19,16);
10453           regM = INSNA(3,0);
10454           if (regD != 15 && regN != 15 && regM != 15)
10455              gate = True;
10456        }
10457     }
10458
10459     if (gate) {
10460        IRTemp rNt   = newTemp(Ity_I32);
10461        IRTemp rMt   = newTemp(Ity_I32);
10462        IRTemp rN_d  = newTemp(Ity_I32);
10463        IRTemp res_q = newTemp(Ity_I32);
10464
10465        assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) );
10466        assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) );
10467
10468        or_into_QFLAG32(
10469           signed_overflow_after_Add32(
10470              binop(Iop_Add32, mkexpr(rNt), mkexpr(rNt)), rNt, rNt),
10471           condT
10472        );
10473
10474        assign(rN_d,  binop(Iop_QAdd32S, mkexpr(rNt), mkexpr(rNt)));
10475        assign(res_q, binop(Iop_QSub32S, mkexpr(rMt), mkexpr(rN_d)));
10476        if (isT)
10477           putIRegT( regD, mkexpr(res_q), condT );
10478        else
10479           putIRegA( regD, mkexpr(res_q), condT, Ijk_Boring );
10480
10481        or_into_QFLAG32(
10482           signed_overflow_after_Sub32(
10483              binop(Iop_Sub32, mkexpr(rMt), mkexpr(rN_d)), rMt, rN_d),
10484           condT
10485        );
10486
10487        DIP("qdsub%s r%u, r%u, r%u\n", nCC(conq),regD,regM,regN);
10488        return True;
10489     }
10490     /* fall through */
10491   }
10492
10493   /* ------------------ uqsub16<c> <Rd>,<Rn>,<Rm> ------------------ */
10494   {
10495     UInt regD = 99, regN = 99, regM = 99;
10496     Bool gate = False;
10497
10498     if (isT) {
10499        if (INSNT0(15,4) == 0xFAD && (INSNT1(15,0) & 0xF0F0) == 0xF050) {
10500           regN = INSNT0(3,0);
10501           regD = INSNT1(11,8);
10502           regM = INSNT1(3,0);
10503           if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
10504              gate = True;
10505        }
10506     } else {
10507        if (INSNA(27,20) == BITS8(0,1,1,0,0,1,1,0) &&
10508            INSNA(11,8)  == BITS4(1,1,1,1)         &&
10509            INSNA(7,4)   == BITS4(0,1,1,1)) {
10510           regD = INSNA(15,12);
10511           regN = INSNA(19,16);
10512           regM = INSNA(3,0);
10513           if (regD != 15 && regN != 15 && regM != 15)
10514             gate = True;
10515        }
10516     }
10517
10518     if (gate) {
10519        IRTemp rNt   = newTemp(Ity_I32);
10520        IRTemp rMt   = newTemp(Ity_I32);
10521        IRTemp res_q = newTemp(Ity_I32);
10522
10523        assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) );
10524        assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) );
10525
10526        assign(res_q, binop(Iop_QSub16Ux2, mkexpr(rNt), mkexpr(rMt)));
10527        if (isT)
10528           putIRegT( regD, mkexpr(res_q), condT );
10529        else
10530           putIRegA( regD, mkexpr(res_q), condT, Ijk_Boring );
10531
10532        DIP("uqsub16%s r%u, r%u, r%u\n", nCC(conq),regD,regN,regM);
10533        return True;
10534     }
10535     /* fall through */
10536   }
10537
10538   /* ----------------- shadd16<c> <Rd>,<Rn>,<Rm> ------------------- */
10539   {
10540     UInt regD = 99, regN = 99, regM = 99;
10541     Bool gate = False;
10542
10543     if (isT) {
10544        if (INSNT0(15,4) == 0xFA9 && (INSNT1(15,0) & 0xF0F0) == 0xF020) {
10545           regN = INSNT0(3,0);
10546           regD = INSNT1(11,8);
10547           regM = INSNT1(3,0);
10548           if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
10549              gate = True;
10550        }
10551     } else {
10552        if (INSNA(27,20) == BITS8(0,1,1,0,0,0,1,1) &&
10553            INSNA(11,8)  == BITS4(1,1,1,1)         &&
10554            INSNA(7,4)   == BITS4(0,0,0,1)) {
10555           regD = INSNA(15,12);
10556           regN = INSNA(19,16);
10557           regM = INSNA(3,0);
10558           if (regD != 15 && regN != 15 && regM != 15)
10559              gate = True;
10560        }
10561     }
10562
10563     if (gate) {
10564        IRTemp rNt   = newTemp(Ity_I32);
10565        IRTemp rMt   = newTemp(Ity_I32);
10566        IRTemp res_q = newTemp(Ity_I32);
10567
10568        assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) );
10569        assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) );
10570
10571        assign(res_q, binop(Iop_HAdd16Sx2, mkexpr(rNt), mkexpr(rMt)));
10572        if (isT)
10573           putIRegT( regD, mkexpr(res_q), condT );
10574        else
10575           putIRegA( regD, mkexpr(res_q), condT, Ijk_Boring );
10576
10577        DIP("shadd16%s r%u, r%u, r%u\n", nCC(conq),regD,regN,regM);
10578        return True;
10579     }
10580     /* fall through */
10581   }
10582
10583   /* ----------------- uhsub8<c> <Rd>,<Rn>,<Rm> ------------------- */
10584   {
10585     UInt regD = 99, regN = 99, regM = 99;
10586     Bool gate = False;
10587
10588     if (isT) {
10589        if (INSNT0(15,4) == 0xFAC && (INSNT1(15,0) & 0xF0F0) == 0xF060) {
10590           regN = INSNT0(3,0);
10591           regD = INSNT1(11,8);
10592           regM = INSNT1(3,0);
10593           if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
10594              gate = True;
10595        }
10596     } else {
10597        if (INSNA(27,20) == BITS8(0,1,1,0,0,1,1,1) &&
10598            INSNA(11,8)  == BITS4(1,1,1,1)         &&
10599            INSNA(7,4)   == BITS4(1,1,1,1)) {
10600           regD = INSNA(15,12);
10601           regN = INSNA(19,16);
10602           regM = INSNA(3,0);
10603           if (regD != 15 && regN != 15 && regM != 15)
10604              gate = True;
10605        }
10606     }
10607
10608     if (gate) {
10609        IRTemp rNt   = newTemp(Ity_I32);
10610        IRTemp rMt   = newTemp(Ity_I32);
10611        IRTemp res_q = newTemp(Ity_I32);
10612
10613        assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) );
10614        assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) );
10615
10616        assign(res_q, binop(Iop_HSub8Ux4, mkexpr(rNt), mkexpr(rMt)));
10617        if (isT)
10618           putIRegT( regD, mkexpr(res_q), condT );
10619        else
10620           putIRegA( regD, mkexpr(res_q), condT, Ijk_Boring );
10621
10622        DIP("uhsub8%s r%u, r%u, r%u\n", nCC(conq),regD,regN,regM);
10623        return True;
10624     }
10625     /* fall through */
10626   }
10627
10628   /* ----------------- uhsub16<c> <Rd>,<Rn>,<Rm> ------------------- */
10629   {
10630     UInt regD = 99, regN = 99, regM = 99;
10631     Bool gate = False;
10632
10633     if (isT) {
10634        if (INSNT0(15,4) == 0xFAD && (INSNT1(15,0) & 0xF0F0) == 0xF060) {
10635           regN = INSNT0(3,0);
10636           regD = INSNT1(11,8);
10637           regM = INSNT1(3,0);
10638           if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
10639              gate = True;
10640        }
10641     } else {
10642        if (INSNA(27,20) == BITS8(0,1,1,0,0,1,1,1) &&
10643            INSNA(11,8)  == BITS4(1,1,1,1)         &&
10644            INSNA(7,4)   == BITS4(0,1,1,1)) {
10645           regD = INSNA(15,12);
10646           regN = INSNA(19,16);
10647           regM = INSNA(3,0);
10648           if (regD != 15 && regN != 15 && regM != 15)
10649              gate = True;
10650        }
10651     }
10652
10653     if (gate) {
10654        IRTemp rNt   = newTemp(Ity_I32);
10655        IRTemp rMt   = newTemp(Ity_I32);
10656        IRTemp res_q = newTemp(Ity_I32);
10657
10658        assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) );
10659        assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) );
10660
10661        assign(res_q, binop(Iop_HSub16Ux2, mkexpr(rNt), mkexpr(rMt)));
10662        if (isT)
10663           putIRegT( regD, mkexpr(res_q), condT );
10664        else
10665           putIRegA( regD, mkexpr(res_q), condT, Ijk_Boring );
10666
10667        DIP("uhsub16%s r%u, r%u, r%u\n", nCC(conq),regD,regN,regM);
10668        return True;
10669     }
10670     /* fall through */
10671   }
10672
10673   /* ---------- Doesn't match anything. ---------- */
10674   return False;
10675
10676#  undef INSNA
10677#  undef INSNT0
10678#  undef INSNT1
10679}
10680
10681
10682/*------------------------------------------------------------*/
10683/*--- LDMxx/STMxx helper (both ARM and Thumb32)            ---*/
10684/*------------------------------------------------------------*/
10685
10686/* Generate IR for LDMxx and STMxx.  This is complex.  Assumes it's
10687   unconditional, so the caller must produce a jump-around before
10688   calling this, if the insn is to be conditional.  Caller is
10689   responsible for all validation of parameters.  For LDMxx, if PC is
10690   amongst the values loaded, caller is also responsible for
10691   generating the jump. */
10692static void mk_ldm_stm ( Bool arm,     /* True: ARM, False: Thumb */
10693                         UInt rN,      /* base reg */
10694                         UInt bINC,    /* 1: inc,  0: dec */
10695                         UInt bBEFORE, /* 1: inc/dec before, 0: after */
10696                         UInt bW,      /* 1: writeback to Rn */
10697                         UInt bL,      /* 1: load, 0: store */
10698                         UInt regList )
10699{
10700   Int i, r, m, nRegs;
10701   IRTemp jk = Ijk_Boring;
10702
10703   /* Get hold of the old Rn value.  We might need to write its value
10704      to memory during a store, and if it's also the writeback
10705      register then we need to get its value now.  We can't treat it
10706      exactly like the other registers we're going to transfer,
10707      because for xxMDA and xxMDB writeback forms, the generated IR
10708      updates Rn in the guest state before any transfers take place.
10709      We have to do this as per comments below, in order that if Rn is
10710      the stack pointer then it always has a value is below or equal
10711      to any of the transfer addresses.  Ick. */
10712   IRTemp oldRnT = newTemp(Ity_I32);
10713   assign(oldRnT, arm ? getIRegA(rN) : getIRegT(rN));
10714
10715   IRTemp anchorT = newTemp(Ity_I32);
10716   /* The old (Addison-Wesley) ARM ARM seems to say that LDMxx/STMxx
10717      ignore the bottom two bits of the address.  However, Cortex-A8
10718      doesn't seem to care.  Hence: */
10719   /* No .. don't force alignment .. */
10720   /* assign(anchorT, binop(Iop_And32, mkexpr(oldRnT), mkU32(~3U))); */
10721   /* Instead, use the potentially misaligned address directly. */
10722   assign(anchorT, mkexpr(oldRnT));
10723
10724   IROp opADDorSUB = bINC ? Iop_Add32 : Iop_Sub32;
10725   // bINC == 1:  xxMIA, xxMIB
10726   // bINC == 0:  xxMDA, xxMDB
10727
10728   // For xxMDA and xxMDB, update Rn first if necessary.  We have
10729   // to do this first so that, for the common idiom of the transfers
10730   // faulting because we're pushing stuff onto a stack and the stack
10731   // is growing down onto allocate-on-fault pages (as Valgrind simulates),
10732   // we need to have the SP up-to-date "covering" (pointing below) the
10733   // transfer area.  For the same reason, if we are doing xxMIA or xxMIB,
10734   // do the transfer first, and then update rN afterwards.
10735   nRegs = 0;
10736   for (i = 0; i < 16; i++) {
10737     if ((regList & (1 << i)) != 0)
10738         nRegs++;
10739   }
10740   if (bW == 1 && !bINC) {
10741      IRExpr* e = binop(opADDorSUB, mkexpr(oldRnT), mkU32(4*nRegs));
10742      if (arm)
10743         putIRegA( rN, e, IRTemp_INVALID, Ijk_Boring );
10744      else
10745         putIRegT( rN, e, IRTemp_INVALID );
10746   }
10747
10748   // Make up a list of the registers to transfer, and their offsets
10749   // in memory relative to the anchor.  If the base reg (Rn) is part
10750   // of the transfer, then do it last for a load and first for a store.
10751   UInt xReg[16], xOff[16];
10752   Int  nX = 0;
10753   m = 0;
10754   for (i = 0; i < 16; i++) {
10755      r = bINC ? i : (15-i);
10756      if (0 == (regList & (1<<r)))
10757         continue;
10758      if (bBEFORE)
10759         m++;
10760      /* paranoia: check we aren't transferring the writeback
10761         register during a load. Should be assured by decode-point
10762         check above. */
10763      if (bW == 1 && bL == 1)
10764         vassert(r != rN);
10765
10766      xOff[nX] = 4 * m;
10767      xReg[nX] = r;
10768      nX++;
10769
10770      if (!bBEFORE)
10771         m++;
10772   }
10773   vassert(m == nRegs);
10774   vassert(nX == nRegs);
10775   vassert(nX <= 16);
10776
10777   if (bW == 0 && (regList & (1<<rN)) != 0) {
10778      /* Non-writeback, and basereg is to be transferred.  Do its
10779         transfer last for a load and first for a store.  Requires
10780         reordering xOff/xReg. */
10781      if (0) {
10782         vex_printf("\nREG_LIST_PRE: (rN=%d)\n", rN);
10783         for (i = 0; i < nX; i++)
10784            vex_printf("reg %d   off %d\n", xReg[i], xOff[i]);
10785         vex_printf("\n");
10786      }
10787
10788      vassert(nX > 0);
10789      for (i = 0; i < nX; i++) {
10790         if (xReg[i] == rN)
10791             break;
10792      }
10793      vassert(i < nX); /* else we didn't find it! */
10794      UInt tReg = xReg[i];
10795      UInt tOff = xOff[i];
10796      if (bL == 1) {
10797         /* load; make this transfer happen last */
10798         if (i < nX-1) {
10799            for (m = i+1; m < nX; m++) {
10800               xReg[m-1] = xReg[m];
10801               xOff[m-1] = xOff[m];
10802            }
10803            vassert(m == nX);
10804            xReg[m-1] = tReg;
10805            xOff[m-1] = tOff;
10806         }
10807      } else {
10808         /* store; make this transfer happen first */
10809         if (i > 0) {
10810            for (m = i-1; m >= 0; m--) {
10811               xReg[m+1] = xReg[m];
10812               xOff[m+1] = xOff[m];
10813            }
10814            vassert(m == -1);
10815            xReg[0] = tReg;
10816            xOff[0] = tOff;
10817         }
10818      }
10819
10820      if (0) {
10821         vex_printf("REG_LIST_POST:\n");
10822         for (i = 0; i < nX; i++)
10823            vex_printf("reg %d   off %d\n", xReg[i], xOff[i]);
10824         vex_printf("\n");
10825      }
10826   }
10827
10828   /* According to the Cortex A8 TRM Sec. 5.2.1, LDM(1) with r13 as the base
10829       register and PC in the register list is a return for purposes of branch
10830       prediction.
10831      The ARM ARM Sec. C9.10.1 further specifies that writeback must be enabled
10832       to be counted in event 0x0E (Procedure return).*/
10833   if (rN == 13 && bL == 1 && bINC && !bBEFORE && bW == 1) {
10834      jk = Ijk_Ret;
10835   }
10836
10837   /* Actually generate the transfers */
10838   for (i = 0; i < nX; i++) {
10839      r = xReg[i];
10840      if (bL == 1) {
10841         IRExpr* e = loadLE(Ity_I32,
10842                            binop(opADDorSUB, mkexpr(anchorT),
10843                                  mkU32(xOff[i])));
10844         if (arm) {
10845            putIRegA( r, e, IRTemp_INVALID, jk );
10846         } else {
10847            // no: putIRegT( r, e, IRTemp_INVALID );
10848            // putIRegT refuses to write to R15.  But that might happen.
10849            // Since this is uncond, and we need to be able to
10850            // write the PC, just use the low level put:
10851            llPutIReg( r, e );
10852         }
10853      } else {
10854         /* if we're storing Rn, make sure we use the correct
10855            value, as per extensive comments above */
10856         storeLE( binop(opADDorSUB, mkexpr(anchorT), mkU32(xOff[i])),
10857                  r == rN ? mkexpr(oldRnT)
10858                          : (arm ? getIRegA(r) : getIRegT(r) ) );
10859      }
10860   }
10861
10862   // If we are doing xxMIA or xxMIB,
10863   // do the transfer first, and then update rN afterwards.
10864   if (bW == 1 && bINC) {
10865      IRExpr* e = binop(opADDorSUB, mkexpr(oldRnT), mkU32(4*nRegs));
10866      if (arm)
10867         putIRegA( rN, e, IRTemp_INVALID, Ijk_Boring );
10868      else
10869         putIRegT( rN, e, IRTemp_INVALID );
10870   }
10871}
10872
10873
10874/*------------------------------------------------------------*/
10875/*--- VFP (CP 10 and 11) instructions                      ---*/
10876/*------------------------------------------------------------*/
10877
10878/* Both ARM and Thumb */
10879
10880/* Translate a CP10 or CP11 instruction.  If successful, returns
10881   True and *dres may or may not be updated.  If failure, returns
10882   False and doesn't change *dres nor create any IR.
10883
10884   The ARM and Thumb encodings are identical for the low 28 bits of
10885   the insn (yay!) and that's what the caller must supply, iow, imm28
10886   has the top 4 bits masked out.  Caller is responsible for
10887   determining whether the masked-out bits are valid for a CP10/11
10888   insn.  The rules for the top 4 bits are:
10889
10890     ARM: 0000 to 1110 allowed, and this is the gating condition.
10891     1111 (NV) is not allowed.
10892
10893     Thumb: must be 1110.  The gating condition is taken from
10894     ITSTATE in the normal way.
10895
10896   Conditionalisation:
10897
10898   Caller must supply an IRTemp 'condT' holding the gating condition,
10899   or IRTemp_INVALID indicating the insn is always executed.
10900
10901   Caller must also supply an ARMCondcode 'cond'.  This is only used
10902   for debug printing, no other purpose.  For ARM, this is simply the
10903   top 4 bits of the original instruction.  For Thumb, the condition
10904   is not (really) known until run time, and so ARMCondAL should be
10905   passed, only so that printing of these instructions does not show
10906   any condition.
10907
10908   Finally, the caller must indicate whether this occurs in ARM or
10909   Thumb code.
10910*/
10911static Bool decode_CP10_CP11_instruction (
10912               /*MOD*/DisResult* dres,
10913               UInt              insn28,
10914               IRTemp            condT,
10915               ARMCondcode       conq,
10916               Bool              isT
10917            )
10918{
10919#  define INSN(_bMax,_bMin)  SLICE_UInt(insn28, (_bMax), (_bMin))
10920
10921   vassert(INSN(31,28) == BITS4(0,0,0,0)); // caller's obligation
10922
10923   if (isT) {
10924      vassert(conq == ARMCondAL);
10925   } else {
10926      vassert(conq >= ARMCondEQ && conq <= ARMCondAL);
10927   }
10928
10929   /* ----------------------------------------------------------- */
10930   /* -- VFP instructions -- double precision (mostly)         -- */
10931   /* ----------------------------------------------------------- */
10932
10933   /* --------------------- fldmx, fstmx --------------------- */
10934   /*
10935                                 31   27   23   19 15 11   7   0
10936                                         P U WL
10937      C4-100, C5-26  1  FSTMX    cond 1100 1000 Rn Dd 1011 offset
10938      C4-100, C5-28  2  FSTMIAX  cond 1100 1010 Rn Dd 1011 offset
10939      C4-100, C5-30  3  FSTMDBX  cond 1101 0010 Rn Dd 1011 offset
10940
10941      C4-42, C5-26   1  FLDMX    cond 1100 1001 Rn Dd 1011 offset
10942      C4-42, C5-28   2  FLDMIAX  cond 1100 1011 Rn Dd 1011 offset
10943      C4-42, C5-30   3  FLDMDBX  cond 1101 0011 Rn Dd 1011 offset
10944
10945      Regs transferred: Dd .. D(d + (offset-3)/2)
10946      offset must be odd, must not imply a reg > 15
10947      IA/DB: Rn is changed by (4 + 8 x # regs transferred)
10948
10949      case coding:
10950         1  at-Rn   (access at Rn)
10951         2  ia-Rn   (access at Rn, then Rn += 4+8n)
10952         3  db-Rn   (Rn -= 4+8n,   then access at Rn)
10953   */
10954   if (BITS8(1,1,0,0,0,0,0,0) == (INSN(27,20) & BITS8(1,1,1,0,0,0,0,0))
10955       && INSN(11,8) == BITS4(1,0,1,1)) {
10956      UInt bP      = (insn28 >> 24) & 1;
10957      UInt bU      = (insn28 >> 23) & 1;
10958      UInt bW      = (insn28 >> 21) & 1;
10959      UInt bL      = (insn28 >> 20) & 1;
10960      UInt offset  = (insn28 >> 0) & 0xFF;
10961      UInt rN      = INSN(19,16);
10962      UInt dD      = (INSN(22,22) << 4) | INSN(15,12);
10963      UInt nRegs   = (offset - 1) / 2;
10964      UInt summary = 0;
10965      Int  i;
10966
10967      /**/ if (bP == 0 && bU == 1 && bW == 0) {
10968         summary = 1;
10969      }
10970      else if (bP == 0 && bU == 1 && bW == 1) {
10971         summary = 2;
10972      }
10973      else if (bP == 1 && bU == 0 && bW == 1) {
10974         summary = 3;
10975      }
10976      else goto after_vfp_fldmx_fstmx;
10977
10978      /* no writebacks to r15 allowed.  No use of r15 in thumb mode. */
10979      if (rN == 15 && (summary == 2 || summary == 3 || isT))
10980         goto after_vfp_fldmx_fstmx;
10981
10982      /* offset must be odd, and specify at least one register */
10983      if (0 == (offset & 1) || offset < 3)
10984         goto after_vfp_fldmx_fstmx;
10985
10986      /* can't transfer regs after D15 */
10987      if (dD + nRegs - 1 >= 32)
10988         goto after_vfp_fldmx_fstmx;
10989
10990      /* Now, we can't do a conditional load or store, since that very
10991         likely will generate an exception.  So we have to take a side
10992         exit at this point if the condition is false. */
10993      if (condT != IRTemp_INVALID) {
10994         if (isT)
10995            mk_skip_over_T32_if_cond_is_false( condT );
10996         else
10997            mk_skip_over_A32_if_cond_is_false( condT );
10998         condT = IRTemp_INVALID;
10999      }
11000      /* Ok, now we're unconditional.  Do the load or store. */
11001
11002      /* get the old Rn value */
11003      IRTemp rnT = newTemp(Ity_I32);
11004      assign(rnT, align4if(isT ? getIRegT(rN) : getIRegA(rN),
11005                           rN == 15));
11006
11007      /* make a new value for Rn, post-insn */
11008      IRTemp rnTnew = IRTemp_INVALID;
11009      if (summary == 2 || summary == 3) {
11010         rnTnew = newTemp(Ity_I32);
11011         assign(rnTnew, binop(summary == 2 ? Iop_Add32 : Iop_Sub32,
11012                              mkexpr(rnT),
11013                              mkU32(4 + 8 * nRegs)));
11014      }
11015
11016      /* decide on the base transfer address */
11017      IRTemp taT = newTemp(Ity_I32);
11018      assign(taT,  summary == 3 ? mkexpr(rnTnew) : mkexpr(rnT));
11019
11020      /* update Rn if necessary -- in case 3, we're moving it down, so
11021         update before any memory reference, in order to keep Memcheck
11022         and V's stack-extending logic (on linux) happy */
11023      if (summary == 3) {
11024         if (isT)
11025            putIRegT(rN, mkexpr(rnTnew), IRTemp_INVALID);
11026         else
11027            putIRegA(rN, mkexpr(rnTnew), IRTemp_INVALID, Ijk_Boring);
11028      }
11029
11030      /* generate the transfers */
11031      for (i = 0; i < nRegs; i++) {
11032         IRExpr* addr = binop(Iop_Add32, mkexpr(taT), mkU32(8*i));
11033         if (bL) {
11034            putDReg(dD + i, loadLE(Ity_F64, addr), IRTemp_INVALID);
11035         } else {
11036            storeLE(addr, getDReg(dD + i));
11037         }
11038      }
11039
11040      /* update Rn if necessary -- in case 2, we're moving it up, so
11041         update after any memory reference, in order to keep Memcheck
11042         and V's stack-extending logic (on linux) happy */
11043      if (summary == 2) {
11044         if (isT)
11045            putIRegT(rN, mkexpr(rnTnew), IRTemp_INVALID);
11046         else
11047            putIRegA(rN, mkexpr(rnTnew), IRTemp_INVALID, Ijk_Boring);
11048      }
11049
11050      HChar* nm = bL==1 ? "ld" : "st";
11051      switch (summary) {
11052         case 1:  DIP("f%smx%s r%u, {d%u-d%u}\n",
11053                      nm, nCC(conq), rN, dD, dD + nRegs - 1);
11054                  break;
11055         case 2:  DIP("f%smiax%s r%u!, {d%u-d%u}\n",
11056                      nm, nCC(conq), rN, dD, dD + nRegs - 1);
11057                  break;
11058         case 3:  DIP("f%smdbx%s r%u!, {d%u-d%u}\n",
11059                      nm, nCC(conq), rN, dD, dD + nRegs - 1);
11060                  break;
11061         default: vassert(0);
11062      }
11063
11064      goto decode_success_vfp;
11065      /* FIXME alignment constraints? */
11066   }
11067
11068  after_vfp_fldmx_fstmx:
11069
11070   /* --------------------- fldmd, fstmd --------------------- */
11071   /*
11072                                 31   27   23   19 15 11   7   0
11073                                         P U WL
11074      C4-96, C5-26   1  FSTMD    cond 1100 1000 Rn Dd 1011 offset
11075      C4-96, C5-28   2  FSTMDIA  cond 1100 1010 Rn Dd 1011 offset
11076      C4-96, C5-30   3  FSTMDDB  cond 1101 0010 Rn Dd 1011 offset
11077
11078      C4-38, C5-26   1  FLDMD    cond 1100 1001 Rn Dd 1011 offset
11079      C4-38, C5-28   2  FLDMIAD  cond 1100 1011 Rn Dd 1011 offset
11080      C4-38, C5-30   3  FLDMDBD  cond 1101 0011 Rn Dd 1011 offset
11081
11082      Regs transferred: Dd .. D(d + (offset-2)/2)
11083      offset must be even, must not imply a reg > 15
11084      IA/DB: Rn is changed by (8 x # regs transferred)
11085
11086      case coding:
11087         1  at-Rn   (access at Rn)
11088         2  ia-Rn   (access at Rn, then Rn += 8n)
11089         3  db-Rn   (Rn -= 8n,     then access at Rn)
11090   */
11091   if (BITS8(1,1,0,0,0,0,0,0) == (INSN(27,20) & BITS8(1,1,1,0,0,0,0,0))
11092       && INSN(11,8) == BITS4(1,0,1,1)) {
11093      UInt bP      = (insn28 >> 24) & 1;
11094      UInt bU      = (insn28 >> 23) & 1;
11095      UInt bW      = (insn28 >> 21) & 1;
11096      UInt bL      = (insn28 >> 20) & 1;
11097      UInt offset  = (insn28 >> 0) & 0xFF;
11098      UInt rN      = INSN(19,16);
11099      UInt dD      = (INSN(22,22) << 4) | INSN(15,12);
11100      UInt nRegs   = offset / 2;
11101      UInt summary = 0;
11102      Int  i;
11103
11104      /**/ if (bP == 0 && bU == 1 && bW == 0) {
11105         summary = 1;
11106      }
11107      else if (bP == 0 && bU == 1 && bW == 1) {
11108         summary = 2;
11109      }
11110      else if (bP == 1 && bU == 0 && bW == 1) {
11111         summary = 3;
11112      }
11113      else goto after_vfp_fldmd_fstmd;
11114
11115      /* no writebacks to r15 allowed.  No use of r15 in thumb mode. */
11116      if (rN == 15 && (summary == 2 || summary == 3 || isT))
11117         goto after_vfp_fldmd_fstmd;
11118
11119      /* offset must be even, and specify at least one register */
11120      if (1 == (offset & 1) || offset < 2)
11121         goto after_vfp_fldmd_fstmd;
11122
11123      /* can't transfer regs after D15 */
11124      if (dD + nRegs - 1 >= 32)
11125         goto after_vfp_fldmd_fstmd;
11126
11127      /* Now, we can't do a conditional load or store, since that very
11128         likely will generate an exception.  So we have to take a side
11129         exit at this point if the condition is false. */
11130      if (condT != IRTemp_INVALID) {
11131         if (isT)
11132            mk_skip_over_T32_if_cond_is_false( condT );
11133         else
11134            mk_skip_over_A32_if_cond_is_false( condT );
11135         condT = IRTemp_INVALID;
11136      }
11137      /* Ok, now we're unconditional.  Do the load or store. */
11138
11139      /* get the old Rn value */
11140      IRTemp rnT = newTemp(Ity_I32);
11141      assign(rnT, align4if(isT ? getIRegT(rN) : getIRegA(rN),
11142                           rN == 15));
11143
11144      /* make a new value for Rn, post-insn */
11145      IRTemp rnTnew = IRTemp_INVALID;
11146      if (summary == 2 || summary == 3) {
11147         rnTnew = newTemp(Ity_I32);
11148         assign(rnTnew, binop(summary == 2 ? Iop_Add32 : Iop_Sub32,
11149                              mkexpr(rnT),
11150                              mkU32(8 * nRegs)));
11151      }
11152
11153      /* decide on the base transfer address */
11154      IRTemp taT = newTemp(Ity_I32);
11155      assign(taT, summary == 3 ? mkexpr(rnTnew) : mkexpr(rnT));
11156
11157      /* update Rn if necessary -- in case 3, we're moving it down, so
11158         update before any memory reference, in order to keep Memcheck
11159         and V's stack-extending logic (on linux) happy */
11160      if (summary == 3) {
11161         if (isT)
11162            putIRegT(rN, mkexpr(rnTnew), IRTemp_INVALID);
11163         else
11164            putIRegA(rN, mkexpr(rnTnew), IRTemp_INVALID, Ijk_Boring);
11165      }
11166
11167      /* generate the transfers */
11168      for (i = 0; i < nRegs; i++) {
11169         IRExpr* addr = binop(Iop_Add32, mkexpr(taT), mkU32(8*i));
11170         if (bL) {
11171            putDReg(dD + i, loadLE(Ity_F64, addr), IRTemp_INVALID);
11172         } else {
11173            storeLE(addr, getDReg(dD + i));
11174         }
11175      }
11176
11177      /* update Rn if necessary -- in case 2, we're moving it up, so
11178         update after any memory reference, in order to keep Memcheck
11179         and V's stack-extending logic (on linux) happy */
11180      if (summary == 2) {
11181         if (isT)
11182            putIRegT(rN, mkexpr(rnTnew), IRTemp_INVALID);
11183         else
11184            putIRegA(rN, mkexpr(rnTnew), IRTemp_INVALID, Ijk_Boring);
11185      }
11186
11187      HChar* nm = bL==1 ? "ld" : "st";
11188      switch (summary) {
11189         case 1:  DIP("f%smd%s r%u, {d%u-d%u}\n",
11190                      nm, nCC(conq), rN, dD, dD + nRegs - 1);
11191                  break;
11192         case 2:  DIP("f%smiad%s r%u!, {d%u-d%u}\n",
11193                      nm, nCC(conq), rN, dD, dD + nRegs - 1);
11194                  break;
11195         case 3:  DIP("f%smdbd%s r%u!, {d%u-d%u}\n",
11196                      nm, nCC(conq), rN, dD, dD + nRegs - 1);
11197                  break;
11198         default: vassert(0);
11199      }
11200
11201      goto decode_success_vfp;
11202      /* FIXME alignment constraints? */
11203   }
11204
11205  after_vfp_fldmd_fstmd:
11206
11207   /* ------------------- fmrx, fmxr ------------------- */
11208   if (BITS8(1,1,1,0,1,1,1,1) == INSN(27,20)
11209       && BITS4(1,0,1,0) == INSN(11,8)
11210       && BITS8(0,0,0,1,0,0,0,0) == (insn28 & 0xFF)) {
11211      UInt rD  = INSN(15,12);
11212      UInt reg = INSN(19,16);
11213      if (reg == BITS4(0,0,0,1)) {
11214         if (rD == 15) {
11215            IRTemp nzcvT = newTemp(Ity_I32);
11216            /* When rD is 15, we are copying the top 4 bits of FPSCR
11217               into CPSR.  That is, set the flags thunk to COPY and
11218               install FPSCR[31:28] as the value to copy. */
11219            assign(nzcvT, binop(Iop_And32,
11220                                IRExpr_Get(OFFB_FPSCR, Ity_I32),
11221                                mkU32(0xF0000000)));
11222            setFlags_D1(ARMG_CC_OP_COPY, nzcvT, condT);
11223            DIP("fmstat%s\n", nCC(conq));
11224         } else {
11225            /* Otherwise, merely transfer FPSCR to r0 .. r14. */
11226            IRExpr* e = IRExpr_Get(OFFB_FPSCR, Ity_I32);
11227            if (isT)
11228               putIRegT(rD, e, condT);
11229            else
11230               putIRegA(rD, e, condT, Ijk_Boring);
11231            DIP("fmrx%s r%u, fpscr\n", nCC(conq), rD);
11232         }
11233         goto decode_success_vfp;
11234      }
11235      /* fall through */
11236   }
11237
11238   if (BITS8(1,1,1,0,1,1,1,0) == INSN(27,20)
11239       && BITS4(1,0,1,0) == INSN(11,8)
11240       && BITS8(0,0,0,1,0,0,0,0) == (insn28 & 0xFF)) {
11241      UInt rD  = INSN(15,12);
11242      UInt reg = INSN(19,16);
11243      if (reg == BITS4(0,0,0,1)) {
11244         putMiscReg32(OFFB_FPSCR,
11245                      isT ? getIRegT(rD) : getIRegA(rD), condT);
11246         DIP("fmxr%s fpscr, r%u\n", nCC(conq), rD);
11247         goto decode_success_vfp;
11248      }
11249      /* fall through */
11250   }
11251
11252   /* --------------------- vmov --------------------- */
11253   // VMOV dM, rD, rN
11254   if (0x0C400B10 == (insn28 & 0x0FF00FD0)) {
11255      UInt dM = INSN(3,0) | (INSN(5,5) << 4);
11256      UInt rD = INSN(15,12); /* lo32 */
11257      UInt rN = INSN(19,16); /* hi32 */
11258      if (rD == 15 || rN == 15 || (isT && (rD == 13 || rN == 13))) {
11259         /* fall through */
11260      } else {
11261         putDReg(dM,
11262                 unop(Iop_ReinterpI64asF64,
11263                      binop(Iop_32HLto64,
11264                            isT ? getIRegT(rN) : getIRegA(rN),
11265                            isT ? getIRegT(rD) : getIRegA(rD))),
11266                 condT);
11267         DIP("vmov%s d%u, r%u, r%u\n", nCC(conq), dM, rD, rN);
11268         goto decode_success_vfp;
11269      }
11270      /* fall through */
11271   }
11272
11273   // VMOV rD, rN, dM
11274   if (0x0C500B10 == (insn28 & 0x0FF00FD0)) {
11275      UInt dM = INSN(3,0) | (INSN(5,5) << 4);
11276      UInt rD = INSN(15,12); /* lo32 */
11277      UInt rN = INSN(19,16); /* hi32 */
11278      if (rD == 15 || rN == 15 || (isT && (rD == 13 || rN == 13))
11279          || rD == rN) {
11280         /* fall through */
11281      } else {
11282         IRTemp i64 = newTemp(Ity_I64);
11283         assign(i64, unop(Iop_ReinterpF64asI64, getDReg(dM)));
11284         IRExpr* hi32 = unop(Iop_64HIto32, mkexpr(i64));
11285         IRExpr* lo32 = unop(Iop_64to32,   mkexpr(i64));
11286         if (isT) {
11287            putIRegT(rN, hi32, condT);
11288            putIRegT(rD, lo32, condT);
11289         } else {
11290            putIRegA(rN, hi32, condT, Ijk_Boring);
11291            putIRegA(rD, lo32, condT, Ijk_Boring);
11292         }
11293         DIP("vmov%s r%u, r%u, d%u\n", nCC(conq), rD, rN, dM);
11294         goto decode_success_vfp;
11295      }
11296      /* fall through */
11297   }
11298
11299   // VMOV sD, sD+1, rN, rM
11300   if (0x0C400A10 == (insn28 & 0x0FF00FD0)) {
11301      UInt sD = (INSN(3,0) << 1) | INSN(5,5);
11302      UInt rN = INSN(15,12);
11303      UInt rM = INSN(19,16);
11304      if (rM == 15 || rN == 15 || (isT && (rM == 13 || rN == 13))
11305          || sD == 31) {
11306         /* fall through */
11307      } else {
11308         putFReg(sD,
11309                 unop(Iop_ReinterpI32asF32, isT ? getIRegT(rN) : getIRegA(rN)),
11310                 condT);
11311         putFReg(sD+1,
11312                 unop(Iop_ReinterpI32asF32, isT ? getIRegT(rM) : getIRegA(rM)),
11313                 condT);
11314         DIP("vmov%s, s%u, s%u, r%u, r%u\n",
11315              nCC(conq), sD, sD + 1, rN, rM);
11316         goto decode_success_vfp;
11317      }
11318   }
11319
11320   // VMOV rN, rM, sD, sD+1
11321   if (0x0C500A10 == (insn28 & 0x0FF00FD0)) {
11322      UInt sD = (INSN(3,0) << 1) | INSN(5,5);
11323      UInt rN = INSN(15,12);
11324      UInt rM = INSN(19,16);
11325      if (rM == 15 || rN == 15 || (isT && (rM == 13 || rN == 13))
11326          || sD == 31 || rN == rM) {
11327         /* fall through */
11328      } else {
11329         IRExpr* res0 = unop(Iop_ReinterpF32asI32, getFReg(sD));
11330         IRExpr* res1 = unop(Iop_ReinterpF32asI32, getFReg(sD+1));
11331         if (isT) {
11332            putIRegT(rN, res0, condT);
11333            putIRegT(rM, res1, condT);
11334         } else {
11335            putIRegA(rN, res0, condT, Ijk_Boring);
11336            putIRegA(rM, res1, condT, Ijk_Boring);
11337         }
11338         DIP("vmov%s, r%u, r%u, s%u, s%u\n",
11339             nCC(conq), rN, rM, sD, sD + 1);
11340         goto decode_success_vfp;
11341      }
11342   }
11343
11344   // VMOV rD[x], rT  (ARM core register to scalar)
11345   if (0x0E000B10 == (insn28 & 0x0F900F1F)) {
11346      UInt rD  = (INSN(7,7) << 4) | INSN(19,16);
11347      UInt rT  = INSN(15,12);
11348      UInt opc = (INSN(22,21) << 2) | INSN(6,5);
11349      UInt index;
11350      if (rT == 15 || (isT && rT == 13)) {
11351         /* fall through */
11352      } else {
11353         if ((opc & BITS4(1,0,0,0)) == BITS4(1,0,0,0)) {
11354            index = opc & 7;
11355            putDRegI64(rD, triop(Iop_SetElem8x8,
11356                                 getDRegI64(rD),
11357                                 mkU8(index),
11358                                 unop(Iop_32to8,
11359                                      isT ? getIRegT(rT) : getIRegA(rT))),
11360                           condT);
11361            DIP("vmov%s.8 d%u[%u], r%u\n", nCC(conq), rD, index, rT);
11362            goto decode_success_vfp;
11363         }
11364         else if ((opc & BITS4(1,0,0,1)) == BITS4(0,0,0,1)) {
11365            index = (opc >> 1) & 3;
11366            putDRegI64(rD, triop(Iop_SetElem16x4,
11367                                 getDRegI64(rD),
11368                                 mkU8(index),
11369                                 unop(Iop_32to16,
11370                                      isT ? getIRegT(rT) : getIRegA(rT))),
11371                           condT);
11372            DIP("vmov%s.16 d%u[%u], r%u\n", nCC(conq), rD, index, rT);
11373            goto decode_success_vfp;
11374         }
11375         else if ((opc & BITS4(1,0,1,1)) == BITS4(0,0,0,0)) {
11376            index = (opc >> 2) & 1;
11377            putDRegI64(rD, triop(Iop_SetElem32x2,
11378                                 getDRegI64(rD),
11379                                 mkU8(index),
11380                                 isT ? getIRegT(rT) : getIRegA(rT)),
11381                           condT);
11382            DIP("vmov%s.32 d%u[%u], r%u\n", nCC(conq), rD, index, rT);
11383            goto decode_success_vfp;
11384         } else {
11385            /* fall through */
11386         }
11387      }
11388   }
11389
11390   // VMOV (scalar to ARM core register)
11391   // VMOV rT, rD[x]
11392   if (0x0E100B10 == (insn28 & 0x0F100F1F)) {
11393      UInt rN  = (INSN(7,7) << 4) | INSN(19,16);
11394      UInt rT  = INSN(15,12);
11395      UInt U   = INSN(23,23);
11396      UInt opc = (INSN(22,21) << 2) | INSN(6,5);
11397      UInt index;
11398      if (rT == 15 || (isT && rT == 13)) {
11399         /* fall through */
11400      } else {
11401         if ((opc & BITS4(1,0,0,0)) == BITS4(1,0,0,0)) {
11402            index = opc & 7;
11403            IRExpr* e = unop(U ? Iop_8Uto32 : Iop_8Sto32,
11404                             binop(Iop_GetElem8x8,
11405                                   getDRegI64(rN),
11406                                   mkU8(index)));
11407            if (isT)
11408               putIRegT(rT, e, condT);
11409            else
11410               putIRegA(rT, e, condT, Ijk_Boring);
11411            DIP("vmov%s.%c8 r%u, d%u[%u]\n", nCC(conq), U ? 'u' : 's',
11412                  rT, rN, index);
11413            goto decode_success_vfp;
11414         }
11415         else if ((opc & BITS4(1,0,0,1)) == BITS4(0,0,0,1)) {
11416            index = (opc >> 1) & 3;
11417            IRExpr* e = unop(U ? Iop_16Uto32 : Iop_16Sto32,
11418                             binop(Iop_GetElem16x4,
11419                                   getDRegI64(rN),
11420                                   mkU8(index)));
11421            if (isT)
11422               putIRegT(rT, e, condT);
11423            else
11424               putIRegA(rT, e, condT, Ijk_Boring);
11425            DIP("vmov%s.%c16 r%u, d%u[%u]\n", nCC(conq), U ? 'u' : 's',
11426                  rT, rN, index);
11427            goto decode_success_vfp;
11428         }
11429         else if ((opc & BITS4(1,0,1,1)) == BITS4(0,0,0,0) && U == 0) {
11430            index = (opc >> 2) & 1;
11431            IRExpr* e = binop(Iop_GetElem32x2, getDRegI64(rN), mkU8(index));
11432            if (isT)
11433               putIRegT(rT, e, condT);
11434            else
11435               putIRegA(rT, e, condT, Ijk_Boring);
11436            DIP("vmov%s.32 r%u, d%u[%u]\n", nCC(conq), rT, rN, index);
11437            goto decode_success_vfp;
11438         } else {
11439            /* fall through */
11440         }
11441      }
11442   }
11443
11444   // VMOV.F32 sD, #imm
11445   // FCONSTS sD, #imm
11446   if (BITS8(1,1,1,0,1,0,1,1) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,1))
11447       && BITS4(0,0,0,0) == INSN(7,4) && INSN(11,8) == BITS4(1,0,1,0)) {
11448      UInt rD   = (INSN(15,12) << 1) | INSN(22,22);
11449      UInt imm8 = (INSN(19,16) << 4) | INSN(3,0);
11450      UInt b    = (imm8 >> 6) & 1;
11451      UInt imm;
11452      imm = (BITS8((imm8 >> 7) & 1,(~b) & 1,b,b,b,b,b,(imm8 >> 5) & 1) << 8)
11453             | ((imm8 & 0x1f) << 3);
11454      imm <<= 16;
11455      putFReg(rD, unop(Iop_ReinterpI32asF32, mkU32(imm)), condT);
11456      DIP("fconsts%s s%u #%u", nCC(conq), rD, imm8);
11457      goto decode_success_vfp;
11458   }
11459
11460   // VMOV.F64 dD, #imm
11461   // FCONSTD dD, #imm
11462   if (BITS8(1,1,1,0,1,0,1,1) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,1))
11463       && BITS4(0,0,0,0) == INSN(7,4) && INSN(11,8) == BITS4(1,0,1,1)) {
11464      UInt rD   = INSN(15,12) | (INSN(22,22) << 4);
11465      UInt imm8 = (INSN(19,16) << 4) | INSN(3,0);
11466      UInt b    = (imm8 >> 6) & 1;
11467      ULong imm;
11468      imm = (BITS8((imm8 >> 7) & 1,(~b) & 1,b,b,b,b,b,b) << 8)
11469             | BITS8(b,b,0,0,0,0,0,0) | (imm8 & 0x3f);
11470      imm <<= 48;
11471      putDReg(rD, unop(Iop_ReinterpI64asF64, mkU64(imm)), condT);
11472      DIP("fconstd%s d%u #%u", nCC(conq), rD, imm8);
11473      goto decode_success_vfp;
11474   }
11475
11476   /* ---------------------- vdup ------------------------- */
11477   // VDUP dD, rT
11478   // VDUP qD, rT
11479   if (BITS8(1,1,1,0,1,0,0,0) == (INSN(27,20) & BITS8(1,1,1,1,1,0,0,1))
11480       && BITS4(1,0,1,1) == INSN(11,8) && INSN(6,6) == 0 && INSN(4,4) == 1) {
11481      UInt rD   = (INSN(7,7) << 4) | INSN(19,16);
11482      UInt rT   = INSN(15,12);
11483      UInt Q    = INSN(21,21);
11484      UInt size = (INSN(22,22) << 1) | INSN(5,5);
11485      if (rT == 15 || (isT && rT == 13) || size == 3 || (Q && (rD & 1))) {
11486         /* fall through */
11487      } else {
11488         IRExpr* e = isT ? getIRegT(rT) : getIRegA(rT);
11489         if (Q) {
11490            rD >>= 1;
11491            switch (size) {
11492               case 0:
11493                  putQReg(rD, unop(Iop_Dup32x4, e), condT);
11494                  break;
11495               case 1:
11496                  putQReg(rD, unop(Iop_Dup16x8, unop(Iop_32to16, e)),
11497                              condT);
11498                  break;
11499               case 2:
11500                  putQReg(rD, unop(Iop_Dup8x16, unop(Iop_32to8, e)),
11501                              condT);
11502                  break;
11503               default:
11504                  vassert(0);
11505            }
11506            DIP("vdup.%u q%u, r%u\n", 32 / (1<<size), rD, rT);
11507         } else {
11508            switch (size) {
11509               case 0:
11510                  putDRegI64(rD, unop(Iop_Dup32x2, e), condT);
11511                  break;
11512               case 1:
11513                  putDRegI64(rD, unop(Iop_Dup16x4, unop(Iop_32to16, e)),
11514                               condT);
11515                  break;
11516               case 2:
11517                  putDRegI64(rD, unop(Iop_Dup8x8, unop(Iop_32to8, e)),
11518                               condT);
11519                  break;
11520               default:
11521                  vassert(0);
11522            }
11523            DIP("vdup.%u d%u, r%u\n", 32 / (1<<size), rD, rT);
11524         }
11525         goto decode_success_vfp;
11526      }
11527   }
11528
11529   /* --------------------- f{ld,st}d --------------------- */
11530   // FLDD, FSTD
11531   if (BITS8(1,1,0,1,0,0,0,0) == (INSN(27,20) & BITS8(1,1,1,1,0,0,1,0))
11532       && BITS4(1,0,1,1) == INSN(11,8)) {
11533      UInt dD     = INSN(15,12) | (INSN(22,22) << 4);
11534      UInt rN     = INSN(19,16);
11535      UInt offset = (insn28 & 0xFF) << 2;
11536      UInt bU     = (insn28 >> 23) & 1; /* 1: +offset  0: -offset */
11537      UInt bL     = (insn28 >> 20) & 1; /* 1: load  0: store */
11538      /* make unconditional */
11539      if (condT != IRTemp_INVALID) {
11540         if (isT)
11541            mk_skip_over_T32_if_cond_is_false( condT );
11542         else
11543            mk_skip_over_A32_if_cond_is_false( condT );
11544         condT = IRTemp_INVALID;
11545      }
11546      IRTemp ea = newTemp(Ity_I32);
11547      assign(ea, binop(bU ? Iop_Add32 : Iop_Sub32,
11548                       align4if(isT ? getIRegT(rN) : getIRegA(rN),
11549                                rN == 15),
11550                       mkU32(offset)));
11551      if (bL) {
11552         putDReg(dD, loadLE(Ity_F64,mkexpr(ea)), IRTemp_INVALID);
11553      } else {
11554         storeLE(mkexpr(ea), getDReg(dD));
11555      }
11556      DIP("f%sd%s d%u, [r%u, %c#%u]\n",
11557          bL ? "ld" : "st", nCC(conq), dD, rN,
11558          bU ? '+' : '-', offset);
11559      goto decode_success_vfp;
11560   }
11561
11562   /* --------------------- dp insns (D) --------------------- */
11563   if (BITS8(1,1,1,0,0,0,0,0) == (INSN(27,20) & BITS8(1,1,1,1,0,0,0,0))
11564       && BITS4(1,0,1,1) == INSN(11,8)
11565       && BITS4(0,0,0,0) == (INSN(7,4) & BITS4(0,0,0,1))) {
11566      UInt    dM  = INSN(3,0)   | (INSN(5,5) << 4);       /* argR */
11567      UInt    dD  = INSN(15,12) | (INSN(22,22) << 4);   /* dst/acc */
11568      UInt    dN  = INSN(19,16) | (INSN(7,7) << 4);     /* argL */
11569      UInt    bP  = (insn28 >> 23) & 1;
11570      UInt    bQ  = (insn28 >> 21) & 1;
11571      UInt    bR  = (insn28 >> 20) & 1;
11572      UInt    bS  = (insn28 >> 6) & 1;
11573      UInt    opc = (bP << 3) | (bQ << 2) | (bR << 1) | bS;
11574      IRExpr* rm  = get_FAKE_roundingmode(); /* XXXROUNDINGFIXME */
11575      switch (opc) {
11576         case BITS4(0,0,0,0): /* MAC: d + n * m */
11577            putDReg(dD, triop(Iop_AddF64, rm,
11578                              getDReg(dD),
11579                              triop(Iop_MulF64, rm, getDReg(dN),
11580                                                    getDReg(dM))),
11581                        condT);
11582            DIP("fmacd%s d%u, d%u, d%u\n", nCC(conq), dD, dN, dM);
11583            goto decode_success_vfp;
11584         case BITS4(0,0,0,1): /* NMAC: d + -(n * m) */
11585            putDReg(dD, triop(Iop_AddF64, rm,
11586                              getDReg(dD),
11587                              unop(Iop_NegF64,
11588                                   triop(Iop_MulF64, rm, getDReg(dN),
11589                                                         getDReg(dM)))),
11590                        condT);
11591            DIP("fnmacd%s d%u, d%u, d%u\n", nCC(conq), dD, dN, dM);
11592            goto decode_success_vfp;
11593         case BITS4(0,0,1,0): /* MSC: - d + n * m */
11594            putDReg(dD, triop(Iop_AddF64, rm,
11595                              unop(Iop_NegF64, getDReg(dD)),
11596                              triop(Iop_MulF64, rm, getDReg(dN),
11597                                                    getDReg(dM))),
11598                        condT);
11599            DIP("fmscd%s d%u, d%u, d%u\n", nCC(conq), dD, dN, dM);
11600            goto decode_success_vfp;
11601         case BITS4(0,0,1,1): /* NMSC: - d + -(n * m) */
11602            putDReg(dD, triop(Iop_AddF64, rm,
11603                              unop(Iop_NegF64, getDReg(dD)),
11604                              unop(Iop_NegF64,
11605                                   triop(Iop_MulF64, rm, getDReg(dN),
11606                                                         getDReg(dM)))),
11607                        condT);
11608            DIP("fnmscd%s d%u, d%u, d%u\n", nCC(conq), dD, dN, dM);
11609            goto decode_success_vfp;
11610         case BITS4(0,1,0,0): /* MUL: n * m */
11611            putDReg(dD, triop(Iop_MulF64, rm, getDReg(dN), getDReg(dM)),
11612                        condT);
11613            DIP("fmuld%s d%u, d%u, d%u\n", nCC(conq), dD, dN, dM);
11614            goto decode_success_vfp;
11615         case BITS4(0,1,0,1): /* NMUL: - n * m */
11616            putDReg(dD, unop(Iop_NegF64,
11617                             triop(Iop_MulF64, rm, getDReg(dN),
11618                                                   getDReg(dM))),
11619                    condT);
11620            DIP("fnmuld%s d%u, d%u, d%u\n", nCC(conq), dD, dN, dM);
11621            goto decode_success_vfp;
11622         case BITS4(0,1,1,0): /* ADD: n + m */
11623            putDReg(dD, triop(Iop_AddF64, rm, getDReg(dN), getDReg(dM)),
11624                        condT);
11625            DIP("faddd%s d%u, d%u, d%u\n", nCC(conq), dD, dN, dM);
11626            goto decode_success_vfp;
11627         case BITS4(0,1,1,1): /* SUB: n - m */
11628            putDReg(dD, triop(Iop_SubF64, rm, getDReg(dN), getDReg(dM)),
11629                        condT);
11630            DIP("fsubd%s d%u, d%u, d%u\n", nCC(conq), dD, dN, dM);
11631            goto decode_success_vfp;
11632         case BITS4(1,0,0,0): /* DIV: n / m */
11633            putDReg(dD, triop(Iop_DivF64, rm, getDReg(dN), getDReg(dM)),
11634                        condT);
11635            DIP("fdivd%s d%u, d%u, d%u\n", nCC(conq), dD, dN, dM);
11636            goto decode_success_vfp;
11637         default:
11638            break;
11639      }
11640   }
11641
11642   /* --------------------- compares (D) --------------------- */
11643   /*          31   27   23   19   15 11   7    3
11644                 28   24   20   16 12    8    4    0
11645      FCMPD    cond 1110 1D11 0100 Dd 1011 0100 Dm
11646      FCMPED   cond 1110 1D11 0100 Dd 1011 1100 Dm
11647      FCMPZD   cond 1110 1D11 0101 Dd 1011 0100 0000
11648      FCMPZED  cond 1110 1D11 0101 Dd 1011 1100 0000
11649                                 Z         N
11650
11651      Z=0 Compare Dd vs Dm     and set FPSCR 31:28 accordingly
11652      Z=1 Compare Dd vs zero
11653
11654      N=1 generates Invalid Operation exn if either arg is any kind of NaN
11655      N=0 generates Invalid Operation exn if either arg is a signalling NaN
11656      (Not that we pay any attention to N here)
11657   */
11658   if (BITS8(1,1,1,0,1,0,1,1) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,1))
11659       && BITS4(0,1,0,0) == (INSN(19,16) & BITS4(1,1,1,0))
11660       && BITS4(1,0,1,1) == INSN(11,8)
11661       && BITS4(0,1,0,0) == (INSN(7,4) & BITS4(0,1,0,1))) {
11662      UInt bZ = (insn28 >> 16) & 1;
11663      UInt bN = (insn28 >> 7) & 1;
11664      UInt dD = INSN(15,12) | (INSN(22,22) << 4);
11665      UInt dM = INSN(3,0) | (INSN(5,5) << 4);
11666      if (bZ && INSN(3,0) != 0) {
11667         /* does not decode; fall through */
11668      } else {
11669         IRTemp argL = newTemp(Ity_F64);
11670         IRTemp argR = newTemp(Ity_F64);
11671         IRTemp irRes = newTemp(Ity_I32);
11672         assign(argL, getDReg(dD));
11673         assign(argR, bZ ? IRExpr_Const(IRConst_F64i(0)) : getDReg(dM));
11674         assign(irRes, binop(Iop_CmpF64, mkexpr(argL), mkexpr(argR)));
11675
11676         IRTemp nzcv     = IRTemp_INVALID;
11677         IRTemp oldFPSCR = newTemp(Ity_I32);
11678         IRTemp newFPSCR = newTemp(Ity_I32);
11679
11680         /* This is where the fun starts.  We have to convert 'irRes'
11681            from an IR-convention return result (IRCmpF64Result) to an
11682            ARM-encoded (N,Z,C,V) group.  The final result is in the
11683            bottom 4 bits of 'nzcv'. */
11684         /* Map compare result from IR to ARM(nzcv) */
11685         /*
11686            FP cmp result | IR   | ARM(nzcv)
11687            --------------------------------
11688            UN              0x45   0011
11689            LT              0x01   1000
11690            GT              0x00   0010
11691            EQ              0x40   0110
11692         */
11693         nzcv = mk_convert_IRCmpF64Result_to_NZCV(irRes);
11694
11695         /* And update FPSCR accordingly */
11696         assign(oldFPSCR, IRExpr_Get(OFFB_FPSCR, Ity_I32));
11697         assign(newFPSCR,
11698                binop(Iop_Or32,
11699                      binop(Iop_And32, mkexpr(oldFPSCR), mkU32(0x0FFFFFFF)),
11700                      binop(Iop_Shl32, mkexpr(nzcv), mkU8(28))));
11701
11702         putMiscReg32(OFFB_FPSCR, mkexpr(newFPSCR), condT);
11703
11704         if (bZ) {
11705            DIP("fcmpz%sd%s d%u\n", bN ? "e" : "", nCC(conq), dD);
11706         } else {
11707            DIP("fcmp%sd%s d%u, d%u\n", bN ? "e" : "", nCC(conq), dD, dM);
11708         }
11709         goto decode_success_vfp;
11710      }
11711      /* fall through */
11712   }
11713
11714   /* --------------------- unary (D) --------------------- */
11715   if (BITS8(1,1,1,0,1,0,1,1) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,1))
11716       && BITS4(0,0,0,0) == (INSN(19,16) & BITS4(1,1,1,0))
11717       && BITS4(1,0,1,1) == INSN(11,8)
11718       && BITS4(0,1,0,0) == (INSN(7,4) & BITS4(0,1,0,1))) {
11719      UInt dD  = INSN(15,12) | (INSN(22,22) << 4);
11720      UInt dM  = INSN(3,0) | (INSN(5,5) << 4);
11721      UInt b16 = (insn28 >> 16) & 1;
11722      UInt b7  = (insn28 >> 7) & 1;
11723      /**/ if (b16 == 0 && b7 == 0) {
11724         // FCPYD
11725         putDReg(dD, getDReg(dM), condT);
11726         DIP("fcpyd%s d%u, d%u\n", nCC(conq), dD, dM);
11727         goto decode_success_vfp;
11728      }
11729      else if (b16 == 0 && b7 == 1) {
11730         // FABSD
11731         putDReg(dD, unop(Iop_AbsF64, getDReg(dM)), condT);
11732         DIP("fabsd%s d%u, d%u\n", nCC(conq), dD, dM);
11733         goto decode_success_vfp;
11734      }
11735      else if (b16 == 1 && b7 == 0) {
11736         // FNEGD
11737         putDReg(dD, unop(Iop_NegF64, getDReg(dM)), condT);
11738         DIP("fnegd%s d%u, d%u\n", nCC(conq), dD, dM);
11739         goto decode_success_vfp;
11740      }
11741      else if (b16 == 1 && b7 == 1) {
11742         // FSQRTD
11743         IRExpr* rm = get_FAKE_roundingmode(); /* XXXROUNDINGFIXME */
11744         putDReg(dD, binop(Iop_SqrtF64, rm, getDReg(dM)), condT);
11745         DIP("fsqrtd%s d%u, d%u\n", nCC(conq), dD, dM);
11746         goto decode_success_vfp;
11747      }
11748      else
11749         vassert(0);
11750
11751      /* fall through */
11752   }
11753
11754   /* ----------------- I <-> D conversions ----------------- */
11755
11756   // F{S,U}ITOD dD, fM
11757   if (BITS8(1,1,1,0,1,0,1,1) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,1))
11758       && BITS4(1,0,0,0) == (INSN(19,16) & BITS4(1,1,1,1))
11759       && BITS4(1,0,1,1) == INSN(11,8)
11760       && BITS4(0,1,0,0) == (INSN(7,4) & BITS4(0,1,0,1))) {
11761      UInt bM    = (insn28 >> 5) & 1;
11762      UInt fM    = (INSN(3,0) << 1) | bM;
11763      UInt dD    = INSN(15,12) | (INSN(22,22) << 4);
11764      UInt syned = (insn28 >> 7) & 1;
11765      if (syned) {
11766         // FSITOD
11767         putDReg(dD, unop(Iop_I32StoF64,
11768                          unop(Iop_ReinterpF32asI32, getFReg(fM))),
11769                 condT);
11770         DIP("fsitod%s d%u, s%u\n", nCC(conq), dD, fM);
11771      } else {
11772         // FUITOD
11773         putDReg(dD, unop(Iop_I32UtoF64,
11774                          unop(Iop_ReinterpF32asI32, getFReg(fM))),
11775                 condT);
11776         DIP("fuitod%s d%u, s%u\n", nCC(conq), dD, fM);
11777      }
11778      goto decode_success_vfp;
11779   }
11780
11781   // FTO{S,U}ID fD, dM
11782   if (BITS8(1,1,1,0,1,0,1,1) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,1))
11783       && BITS4(1,1,0,0) == (INSN(19,16) & BITS4(1,1,1,0))
11784       && BITS4(1,0,1,1) == INSN(11,8)
11785       && BITS4(0,1,0,0) == (INSN(7,4) & BITS4(0,1,0,1))) {
11786      UInt   bD    = (insn28 >> 22) & 1;
11787      UInt   fD    = (INSN(15,12) << 1) | bD;
11788      UInt   dM    = INSN(3,0) | (INSN(5,5) << 4);
11789      UInt   bZ    = (insn28 >> 7) & 1;
11790      UInt   syned = (insn28 >> 16) & 1;
11791      IRTemp rmode = newTemp(Ity_I32);
11792      assign(rmode, bZ ? mkU32(Irrm_ZERO)
11793                       : mkexpr(mk_get_IR_rounding_mode()));
11794      if (syned) {
11795         // FTOSID
11796         putFReg(fD, unop(Iop_ReinterpI32asF32,
11797                          binop(Iop_F64toI32S, mkexpr(rmode),
11798                                getDReg(dM))),
11799                 condT);
11800         DIP("ftosi%sd%s s%u, d%u\n", bZ ? "z" : "",
11801             nCC(conq), fD, dM);
11802      } else {
11803         // FTOUID
11804         putFReg(fD, unop(Iop_ReinterpI32asF32,
11805                          binop(Iop_F64toI32U, mkexpr(rmode),
11806                                getDReg(dM))),
11807                 condT);
11808         DIP("ftoui%sd%s s%u, d%u\n", bZ ? "z" : "",
11809             nCC(conq), fD, dM);
11810      }
11811      goto decode_success_vfp;
11812   }
11813
11814   /* ----------------------------------------------------------- */
11815   /* -- VFP instructions -- single precision                  -- */
11816   /* ----------------------------------------------------------- */
11817
11818   /* --------------------- fldms, fstms --------------------- */
11819   /*
11820                                 31   27   23   19 15 11   7   0
11821                                         P UDWL
11822      C4-98, C5-26   1  FSTMD    cond 1100 1x00 Rn Fd 1010 offset
11823      C4-98, C5-28   2  FSTMDIA  cond 1100 1x10 Rn Fd 1010 offset
11824      C4-98, C5-30   3  FSTMDDB  cond 1101 0x10 Rn Fd 1010 offset
11825
11826      C4-40, C5-26   1  FLDMD    cond 1100 1x01 Rn Fd 1010 offset
11827      C4-40, C5-26   2  FLDMIAD  cond 1100 1x11 Rn Fd 1010 offset
11828      C4-40, C5-26   3  FLDMDBD  cond 1101 0x11 Rn Fd 1010 offset
11829
11830      Regs transferred: F(Fd:D) .. F(Fd:d + offset)
11831      offset must not imply a reg > 15
11832      IA/DB: Rn is changed by (4 x # regs transferred)
11833
11834      case coding:
11835         1  at-Rn   (access at Rn)
11836         2  ia-Rn   (access at Rn, then Rn += 4n)
11837         3  db-Rn   (Rn -= 4n,     then access at Rn)
11838   */
11839   if (BITS8(1,1,0,0,0,0,0,0) == (INSN(27,20) & BITS8(1,1,1,0,0,0,0,0))
11840       && INSN(11,8) == BITS4(1,0,1,0)) {
11841      UInt bP      = (insn28 >> 24) & 1;
11842      UInt bU      = (insn28 >> 23) & 1;
11843      UInt bW      = (insn28 >> 21) & 1;
11844      UInt bL      = (insn28 >> 20) & 1;
11845      UInt bD      = (insn28 >> 22) & 1;
11846      UInt offset  = (insn28 >> 0) & 0xFF;
11847      UInt rN      = INSN(19,16);
11848      UInt fD      = (INSN(15,12) << 1) | bD;
11849      UInt nRegs   = offset;
11850      UInt summary = 0;
11851      Int  i;
11852
11853      /**/ if (bP == 0 && bU == 1 && bW == 0) {
11854         summary = 1;
11855      }
11856      else if (bP == 0 && bU == 1 && bW == 1) {
11857         summary = 2;
11858      }
11859      else if (bP == 1 && bU == 0 && bW == 1) {
11860         summary = 3;
11861      }
11862      else goto after_vfp_fldms_fstms;
11863
11864      /* no writebacks to r15 allowed.  No use of r15 in thumb mode. */
11865      if (rN == 15 && (summary == 2 || summary == 3 || isT))
11866         goto after_vfp_fldms_fstms;
11867
11868      /* offset must specify at least one register */
11869      if (offset < 1)
11870         goto after_vfp_fldms_fstms;
11871
11872      /* can't transfer regs after S31 */
11873      if (fD + nRegs - 1 >= 32)
11874         goto after_vfp_fldms_fstms;
11875
11876      /* Now, we can't do a conditional load or store, since that very
11877         likely will generate an exception.  So we have to take a side
11878         exit at this point if the condition is false. */
11879      if (condT != IRTemp_INVALID) {
11880         if (isT)
11881            mk_skip_over_T32_if_cond_is_false( condT );
11882         else
11883            mk_skip_over_A32_if_cond_is_false( condT );
11884         condT = IRTemp_INVALID;
11885      }
11886      /* Ok, now we're unconditional.  Do the load or store. */
11887
11888      /* get the old Rn value */
11889      IRTemp rnT = newTemp(Ity_I32);
11890      assign(rnT, align4if(isT ? getIRegT(rN) : getIRegA(rN),
11891                           rN == 15));
11892
11893      /* make a new value for Rn, post-insn */
11894      IRTemp rnTnew = IRTemp_INVALID;
11895      if (summary == 2 || summary == 3) {
11896         rnTnew = newTemp(Ity_I32);
11897         assign(rnTnew, binop(summary == 2 ? Iop_Add32 : Iop_Sub32,
11898                              mkexpr(rnT),
11899                              mkU32(4 * nRegs)));
11900      }
11901
11902      /* decide on the base transfer address */
11903      IRTemp taT = newTemp(Ity_I32);
11904      assign(taT, summary == 3 ? mkexpr(rnTnew) : mkexpr(rnT));
11905
11906      /* update Rn if necessary -- in case 3, we're moving it down, so
11907         update before any memory reference, in order to keep Memcheck
11908         and V's stack-extending logic (on linux) happy */
11909      if (summary == 3) {
11910         if (isT)
11911            putIRegT(rN, mkexpr(rnTnew), IRTemp_INVALID);
11912         else
11913            putIRegA(rN, mkexpr(rnTnew), IRTemp_INVALID, Ijk_Boring);
11914      }
11915
11916      /* generate the transfers */
11917      for (i = 0; i < nRegs; i++) {
11918         IRExpr* addr = binop(Iop_Add32, mkexpr(taT), mkU32(4*i));
11919         if (bL) {
11920            putFReg(fD + i, loadLE(Ity_F32, addr), IRTemp_INVALID);
11921         } else {
11922            storeLE(addr, getFReg(fD + i));
11923         }
11924      }
11925
11926      /* update Rn if necessary -- in case 2, we're moving it up, so
11927         update after any memory reference, in order to keep Memcheck
11928         and V's stack-extending logic (on linux) happy */
11929      if (summary == 2) {
11930         if (isT)
11931            putIRegT(rN, mkexpr(rnTnew), IRTemp_INVALID);
11932         else
11933            putIRegA(rN, mkexpr(rnTnew), IRTemp_INVALID, Ijk_Boring);
11934      }
11935
11936      HChar* nm = bL==1 ? "ld" : "st";
11937      switch (summary) {
11938         case 1:  DIP("f%sms%s r%u, {s%u-s%u}\n",
11939                      nm, nCC(conq), rN, fD, fD + nRegs - 1);
11940                  break;
11941         case 2:  DIP("f%smias%s r%u!, {s%u-s%u}\n",
11942                      nm, nCC(conq), rN, fD, fD + nRegs - 1);
11943                  break;
11944         case 3:  DIP("f%smdbs%s r%u!, {s%u-s%u}\n",
11945                      nm, nCC(conq), rN, fD, fD + nRegs - 1);
11946                  break;
11947         default: vassert(0);
11948      }
11949
11950      goto decode_success_vfp;
11951      /* FIXME alignment constraints? */
11952   }
11953
11954  after_vfp_fldms_fstms:
11955
11956   /* --------------------- fmsr, fmrs --------------------- */
11957   if (BITS8(1,1,1,0,0,0,0,0) == (INSN(27,20) & BITS8(1,1,1,1,1,1,1,0))
11958       && BITS4(1,0,1,0) == INSN(11,8)
11959       && BITS4(0,0,0,0) == INSN(3,0)
11960       && BITS4(0,0,0,1) == (INSN(7,4) & BITS4(0,1,1,1))) {
11961      UInt rD  = INSN(15,12);
11962      UInt b7  = (insn28 >> 7) & 1;
11963      UInt fN  = (INSN(19,16) << 1) | b7;
11964      UInt b20 = (insn28 >> 20) & 1;
11965      if (rD == 15) {
11966         /* fall through */
11967         /* Let's assume that no sane person would want to do
11968            floating-point transfers to or from the program counter,
11969            and simply decline to decode the instruction.  The ARM ARM
11970            doesn't seem to explicitly disallow this case, though. */
11971      } else {
11972         if (b20) {
11973            IRExpr* res = unop(Iop_ReinterpF32asI32, getFReg(fN));
11974            if (isT)
11975               putIRegT(rD, res, condT);
11976            else
11977               putIRegA(rD, res, condT, Ijk_Boring);
11978            DIP("fmrs%s r%u, s%u\n", nCC(conq), rD, fN);
11979         } else {
11980            putFReg(fN, unop(Iop_ReinterpI32asF32,
11981                             isT ? getIRegT(rD) : getIRegA(rD)),
11982                        condT);
11983            DIP("fmsr%s s%u, r%u\n", nCC(conq), fN, rD);
11984         }
11985         goto decode_success_vfp;
11986      }
11987      /* fall through */
11988   }
11989
11990   /* --------------------- f{ld,st}s --------------------- */
11991   // FLDS, FSTS
11992   if (BITS8(1,1,0,1,0,0,0,0) == (INSN(27,20) & BITS8(1,1,1,1,0,0,1,0))
11993       && BITS4(1,0,1,0) == INSN(11,8)) {
11994      UInt bD     = (insn28 >> 22) & 1;
11995      UInt fD     = (INSN(15,12) << 1) | bD;
11996      UInt rN     = INSN(19,16);
11997      UInt offset = (insn28 & 0xFF) << 2;
11998      UInt bU     = (insn28 >> 23) & 1; /* 1: +offset  0: -offset */
11999      UInt bL     = (insn28 >> 20) & 1; /* 1: load  0: store */
12000      /* make unconditional */
12001      if (condT != IRTemp_INVALID) {
12002         if (isT)
12003            mk_skip_over_T32_if_cond_is_false( condT );
12004         else
12005            mk_skip_over_A32_if_cond_is_false( condT );
12006         condT = IRTemp_INVALID;
12007      }
12008      IRTemp ea = newTemp(Ity_I32);
12009      assign(ea, binop(bU ? Iop_Add32 : Iop_Sub32,
12010                       align4if(isT ? getIRegT(rN) : getIRegA(rN),
12011                                rN == 15),
12012                       mkU32(offset)));
12013      if (bL) {
12014         putFReg(fD, loadLE(Ity_F32,mkexpr(ea)), IRTemp_INVALID);
12015      } else {
12016         storeLE(mkexpr(ea), getFReg(fD));
12017      }
12018      DIP("f%ss%s s%u, [r%u, %c#%u]\n",
12019          bL ? "ld" : "st", nCC(conq), fD, rN,
12020          bU ? '+' : '-', offset);
12021      goto decode_success_vfp;
12022   }
12023
12024   /* --------------------- dp insns (F) --------------------- */
12025   if (BITS8(1,1,1,0,0,0,0,0) == (INSN(27,20) & BITS8(1,1,1,1,0,0,0,0))
12026       && BITS4(1,0,1,0) == (INSN(11,8) & BITS4(1,1,1,0))
12027       && BITS4(0,0,0,0) == (INSN(7,4) & BITS4(0,0,0,1))) {
12028      UInt    bM  = (insn28 >> 5) & 1;
12029      UInt    bD  = (insn28 >> 22) & 1;
12030      UInt    bN  = (insn28 >> 7) & 1;
12031      UInt    fM  = (INSN(3,0) << 1) | bM;   /* argR */
12032      UInt    fD  = (INSN(15,12) << 1) | bD; /* dst/acc */
12033      UInt    fN  = (INSN(19,16) << 1) | bN; /* argL */
12034      UInt    bP  = (insn28 >> 23) & 1;
12035      UInt    bQ  = (insn28 >> 21) & 1;
12036      UInt    bR  = (insn28 >> 20) & 1;
12037      UInt    bS  = (insn28 >> 6) & 1;
12038      UInt    opc = (bP << 3) | (bQ << 2) | (bR << 1) | bS;
12039      IRExpr* rm  = get_FAKE_roundingmode(); /* XXXROUNDINGFIXME */
12040      switch (opc) {
12041         case BITS4(0,0,0,0): /* MAC: d + n * m */
12042            putFReg(fD, triop(Iop_AddF32, rm,
12043                              getFReg(fD),
12044                              triop(Iop_MulF32, rm, getFReg(fN), getFReg(fM))),
12045                        condT);
12046            DIP("fmacs%s s%u, s%u, s%u\n", nCC(conq), fD, fN, fM);
12047            goto decode_success_vfp;
12048         case BITS4(0,0,0,1): /* NMAC: d + -(n * m) */
12049            putFReg(fD, triop(Iop_AddF32, rm,
12050                              getFReg(fD),
12051                              unop(Iop_NegF32,
12052                                   triop(Iop_MulF32, rm, getFReg(fN),
12053                                                         getFReg(fM)))),
12054                        condT);
12055            DIP("fnmacs%s s%u, s%u, s%u\n", nCC(conq), fD, fN, fM);
12056            goto decode_success_vfp;
12057         case BITS4(0,0,1,0): /* MSC: - d + n * m */
12058            putFReg(fD, triop(Iop_AddF32, rm,
12059                              unop(Iop_NegF32, getFReg(fD)),
12060                              triop(Iop_MulF32, rm, getFReg(fN), getFReg(fM))),
12061                        condT);
12062            DIP("fmscs%s s%u, s%u, s%u\n", nCC(conq), fD, fN, fM);
12063            goto decode_success_vfp;
12064         case BITS4(0,0,1,1): /* NMSC: - d + -(n * m) */
12065            putFReg(fD, triop(Iop_AddF32, rm,
12066                              unop(Iop_NegF32, getFReg(fD)),
12067                              unop(Iop_NegF32,
12068                                   triop(Iop_MulF32, rm,
12069                                                     getFReg(fN),
12070                                                    getFReg(fM)))),
12071                        condT);
12072            DIP("fnmscs%s s%u, s%u, s%u\n", nCC(conq), fD, fN, fM);
12073            goto decode_success_vfp;
12074         case BITS4(0,1,0,0): /* MUL: n * m */
12075            putFReg(fD, triop(Iop_MulF32, rm, getFReg(fN), getFReg(fM)),
12076                        condT);
12077            DIP("fmuls%s s%u, s%u, s%u\n", nCC(conq), fD, fN, fM);
12078            goto decode_success_vfp;
12079         case BITS4(0,1,0,1): /* NMUL: - n * m */
12080            putFReg(fD, unop(Iop_NegF32,
12081                             triop(Iop_MulF32, rm, getFReg(fN),
12082                                                   getFReg(fM))),
12083                    condT);
12084            DIP("fnmuls%s s%u, s%u, s%u\n", nCC(conq), fD, fN, fM);
12085            goto decode_success_vfp;
12086         case BITS4(0,1,1,0): /* ADD: n + m */
12087            putFReg(fD, triop(Iop_AddF32, rm, getFReg(fN), getFReg(fM)),
12088                        condT);
12089            DIP("fadds%s s%u, s%u, s%u\n", nCC(conq), fD, fN, fM);
12090            goto decode_success_vfp;
12091         case BITS4(0,1,1,1): /* SUB: n - m */
12092            putFReg(fD, triop(Iop_SubF32, rm, getFReg(fN), getFReg(fM)),
12093                        condT);
12094            DIP("fsubs%s s%u, s%u, s%u\n", nCC(conq), fD, fN, fM);
12095            goto decode_success_vfp;
12096         case BITS4(1,0,0,0): /* DIV: n / m */
12097            putFReg(fD, triop(Iop_DivF32, rm, getFReg(fN), getFReg(fM)),
12098                        condT);
12099            DIP("fdivs%s s%u, s%u, s%u\n", nCC(conq), fD, fN, fM);
12100            goto decode_success_vfp;
12101         default:
12102            break;
12103      }
12104   }
12105
12106   /* --------------------- compares (S) --------------------- */
12107   /*          31   27   23   19   15 11   7    3
12108                 28   24   20   16 12    8    4    0
12109      FCMPS    cond 1110 1D11 0100 Fd 1010 01M0 Fm
12110      FCMPES   cond 1110 1D11 0100 Fd 1010 11M0 Fm
12111      FCMPZS   cond 1110 1D11 0101 Fd 1010 0100 0000
12112      FCMPZED  cond 1110 1D11 0101 Fd 1010 1100 0000
12113                                 Z         N
12114
12115      Z=0 Compare Fd:D vs Fm:M     and set FPSCR 31:28 accordingly
12116      Z=1 Compare Fd:D vs zero
12117
12118      N=1 generates Invalid Operation exn if either arg is any kind of NaN
12119      N=0 generates Invalid Operation exn if either arg is a signalling NaN
12120      (Not that we pay any attention to N here)
12121   */
12122   if (BITS8(1,1,1,0,1,0,1,1) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,1))
12123       && BITS4(0,1,0,0) == (INSN(19,16) & BITS4(1,1,1,0))
12124       && BITS4(1,0,1,0) == INSN(11,8)
12125       && BITS4(0,1,0,0) == (INSN(7,4) & BITS4(0,1,0,1))) {
12126      UInt bZ = (insn28 >> 16) & 1;
12127      UInt bN = (insn28 >> 7) & 1;
12128      UInt bD = (insn28 >> 22) & 1;
12129      UInt bM = (insn28 >> 5) & 1;
12130      UInt fD = (INSN(15,12) << 1) | bD;
12131      UInt fM = (INSN(3,0) << 1) | bM;
12132      if (bZ && (INSN(3,0) != 0 || (INSN(7,4) & 3) != 0)) {
12133         /* does not decode; fall through */
12134      } else {
12135         IRTemp argL = newTemp(Ity_F64);
12136         IRTemp argR = newTemp(Ity_F64);
12137         IRTemp irRes = newTemp(Ity_I32);
12138
12139         assign(argL, unop(Iop_F32toF64, getFReg(fD)));
12140         assign(argR, bZ ? IRExpr_Const(IRConst_F64i(0))
12141                         : unop(Iop_F32toF64, getFReg(fM)));
12142         assign(irRes, binop(Iop_CmpF64, mkexpr(argL), mkexpr(argR)));
12143
12144         IRTemp nzcv     = IRTemp_INVALID;
12145         IRTemp oldFPSCR = newTemp(Ity_I32);
12146         IRTemp newFPSCR = newTemp(Ity_I32);
12147
12148         /* This is where the fun starts.  We have to convert 'irRes'
12149            from an IR-convention return result (IRCmpF64Result) to an
12150            ARM-encoded (N,Z,C,V) group.  The final result is in the
12151            bottom 4 bits of 'nzcv'. */
12152         /* Map compare result from IR to ARM(nzcv) */
12153         /*
12154            FP cmp result | IR   | ARM(nzcv)
12155            --------------------------------
12156            UN              0x45   0011
12157            LT              0x01   1000
12158            GT              0x00   0010
12159            EQ              0x40   0110
12160         */
12161         nzcv = mk_convert_IRCmpF64Result_to_NZCV(irRes);
12162
12163         /* And update FPSCR accordingly */
12164         assign(oldFPSCR, IRExpr_Get(OFFB_FPSCR, Ity_I32));
12165         assign(newFPSCR,
12166                binop(Iop_Or32,
12167                      binop(Iop_And32, mkexpr(oldFPSCR), mkU32(0x0FFFFFFF)),
12168                      binop(Iop_Shl32, mkexpr(nzcv), mkU8(28))));
12169
12170         putMiscReg32(OFFB_FPSCR, mkexpr(newFPSCR), condT);
12171
12172         if (bZ) {
12173            DIP("fcmpz%ss%s s%u\n", bN ? "e" : "", nCC(conq), fD);
12174         } else {
12175            DIP("fcmp%ss%s s%u, s%u\n", bN ? "e" : "",
12176                nCC(conq), fD, fM);
12177         }
12178         goto decode_success_vfp;
12179      }
12180      /* fall through */
12181   }
12182
12183   /* --------------------- unary (S) --------------------- */
12184   if (BITS8(1,1,1,0,1,0,1,1) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,1))
12185       && BITS4(0,0,0,0) == (INSN(19,16) & BITS4(1,1,1,0))
12186       && BITS4(1,0,1,0) == INSN(11,8)
12187       && BITS4(0,1,0,0) == (INSN(7,4) & BITS4(0,1,0,1))) {
12188      UInt bD = (insn28 >> 22) & 1;
12189      UInt bM = (insn28 >> 5) & 1;
12190      UInt fD  = (INSN(15,12) << 1) | bD;
12191      UInt fM  = (INSN(3,0) << 1) | bM;
12192      UInt b16 = (insn28 >> 16) & 1;
12193      UInt b7  = (insn28 >> 7) & 1;
12194      /**/ if (b16 == 0 && b7 == 0) {
12195         // FCPYS
12196         putFReg(fD, getFReg(fM), condT);
12197         DIP("fcpys%s s%u, s%u\n", nCC(conq), fD, fM);
12198         goto decode_success_vfp;
12199      }
12200      else if (b16 == 0 && b7 == 1) {
12201         // FABSS
12202         putFReg(fD, unop(Iop_AbsF32, getFReg(fM)), condT);
12203         DIP("fabss%s s%u, s%u\n", nCC(conq), fD, fM);
12204         goto decode_success_vfp;
12205      }
12206      else if (b16 == 1 && b7 == 0) {
12207         // FNEGS
12208         putFReg(fD, unop(Iop_NegF32, getFReg(fM)), condT);
12209         DIP("fnegs%s s%u, s%u\n", nCC(conq), fD, fM);
12210         goto decode_success_vfp;
12211      }
12212      else if (b16 == 1 && b7 == 1) {
12213         // FSQRTS
12214         IRExpr* rm = get_FAKE_roundingmode(); /* XXXROUNDINGFIXME */
12215         putFReg(fD, binop(Iop_SqrtF32, rm, getFReg(fM)), condT);
12216         DIP("fsqrts%s s%u, s%u\n", nCC(conq), fD, fM);
12217         goto decode_success_vfp;
12218      }
12219      else
12220         vassert(0);
12221
12222      /* fall through */
12223   }
12224
12225   /* ----------------- I <-> S conversions ----------------- */
12226
12227   // F{S,U}ITOS fD, fM
12228   /* These are more complex than FSITOD/FUITOD.  In the D cases, a 32
12229      bit int will always fit within the 53 bit mantissa, so there's
12230      no possibility of a loss of precision, but that's obviously not
12231      the case here.  Hence this case possibly requires rounding, and
12232      so it drags in the current rounding mode. */
12233   if (BITS8(1,1,1,0,1,0,1,1) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,1))
12234       && BITS4(1,0,0,0) == INSN(19,16)
12235       && BITS4(1,0,1,0) == (INSN(11,8) & BITS4(1,1,1,0))
12236       && BITS4(0,1,0,0) == (INSN(7,4) & BITS4(0,1,0,1))) {
12237      UInt bM    = (insn28 >> 5) & 1;
12238      UInt bD    = (insn28 >> 22) & 1;
12239      UInt fM    = (INSN(3,0) << 1) | bM;
12240      UInt fD    = (INSN(15,12) << 1) | bD;
12241      UInt syned = (insn28 >> 7) & 1;
12242      IRTemp rmode = newTemp(Ity_I32);
12243      assign(rmode, mkexpr(mk_get_IR_rounding_mode()));
12244      if (syned) {
12245         // FSITOS
12246         putFReg(fD, binop(Iop_F64toF32,
12247                           mkexpr(rmode),
12248                           unop(Iop_I32StoF64,
12249                                unop(Iop_ReinterpF32asI32, getFReg(fM)))),
12250                 condT);
12251         DIP("fsitos%s s%u, s%u\n", nCC(conq), fD, fM);
12252      } else {
12253         // FUITOS
12254         putFReg(fD, binop(Iop_F64toF32,
12255                           mkexpr(rmode),
12256                           unop(Iop_I32UtoF64,
12257                                unop(Iop_ReinterpF32asI32, getFReg(fM)))),
12258                 condT);
12259         DIP("fuitos%s s%u, s%u\n", nCC(conq), fD, fM);
12260      }
12261      goto decode_success_vfp;
12262   }
12263
12264   // FTO{S,U}IS fD, fM
12265   if (BITS8(1,1,1,0,1,0,1,1) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,1))
12266       && BITS4(1,1,0,0) == (INSN(19,16) & BITS4(1,1,1,0))
12267       && BITS4(1,0,1,0) == INSN(11,8)
12268       && BITS4(0,1,0,0) == (INSN(7,4) & BITS4(0,1,0,1))) {
12269      UInt   bM    = (insn28 >> 5) & 1;
12270      UInt   bD    = (insn28 >> 22) & 1;
12271      UInt   fD    = (INSN(15,12) << 1) | bD;
12272      UInt   fM    = (INSN(3,0) << 1) | bM;
12273      UInt   bZ    = (insn28 >> 7) & 1;
12274      UInt   syned = (insn28 >> 16) & 1;
12275      IRTemp rmode = newTemp(Ity_I32);
12276      assign(rmode, bZ ? mkU32(Irrm_ZERO)
12277                       : mkexpr(mk_get_IR_rounding_mode()));
12278      if (syned) {
12279         // FTOSIS
12280         putFReg(fD, unop(Iop_ReinterpI32asF32,
12281                          binop(Iop_F64toI32S, mkexpr(rmode),
12282                                unop(Iop_F32toF64, getFReg(fM)))),
12283                 condT);
12284         DIP("ftosi%ss%s s%u, d%u\n", bZ ? "z" : "",
12285             nCC(conq), fD, fM);
12286         goto decode_success_vfp;
12287      } else {
12288         // FTOUIS
12289         putFReg(fD, unop(Iop_ReinterpI32asF32,
12290                          binop(Iop_F64toI32U, mkexpr(rmode),
12291                                unop(Iop_F32toF64, getFReg(fM)))),
12292                 condT);
12293         DIP("ftoui%ss%s s%u, d%u\n", bZ ? "z" : "",
12294             nCC(conq), fD, fM);
12295         goto decode_success_vfp;
12296      }
12297   }
12298
12299   /* ----------------- S <-> D conversions ----------------- */
12300
12301   // FCVTDS
12302   if (BITS8(1,1,1,0,1,0,1,1) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,1))
12303       && BITS4(0,1,1,1) == INSN(19,16)
12304       && BITS4(1,0,1,0) == INSN(11,8)
12305       && BITS4(1,1,0,0) == (INSN(7,4) & BITS4(1,1,0,1))) {
12306      UInt dD = INSN(15,12) | (INSN(22,22) << 4);
12307      UInt bM = (insn28 >> 5) & 1;
12308      UInt fM = (INSN(3,0) << 1) | bM;
12309      putDReg(dD, unop(Iop_F32toF64, getFReg(fM)), condT);
12310      DIP("fcvtds%s d%u, s%u\n", nCC(conq), dD, fM);
12311      goto decode_success_vfp;
12312   }
12313
12314   // FCVTSD
12315   if (BITS8(1,1,1,0,1,0,1,1) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,1))
12316       && BITS4(0,1,1,1) == INSN(19,16)
12317       && BITS4(1,0,1,1) == INSN(11,8)
12318       && BITS4(1,1,0,0) == (INSN(7,4) & BITS4(1,1,0,1))) {
12319      UInt   bD    = (insn28 >> 22) & 1;
12320      UInt   fD    = (INSN(15,12) << 1) | bD;
12321      UInt   dM    = INSN(3,0) | (INSN(5,5) << 4);
12322      IRTemp rmode = newTemp(Ity_I32);
12323      assign(rmode, mkexpr(mk_get_IR_rounding_mode()));
12324      putFReg(fD, binop(Iop_F64toF32, mkexpr(rmode), getDReg(dM)),
12325                  condT);
12326      DIP("fcvtsd%s s%u, d%u\n", nCC(conq), fD, dM);
12327      goto decode_success_vfp;
12328   }
12329
12330   /* --------------- VCVT fixed<->floating, VFP --------------- */
12331   /*          31   27   23   19   15 11   7    3
12332                 28   24   20   16 12    8    4    0
12333
12334               cond 1110 1D11 1p1U Vd 101f x1i0 imm4
12335
12336      VCVT<c>.<Td>.F64 <Dd>, <Dd>, #fbits
12337      VCVT<c>.<Td>.F32 <Dd>, <Dd>, #fbits
12338      VCVT<c>.F64.<Td> <Dd>, <Dd>, #fbits
12339      VCVT<c>.F32.<Td> <Dd>, <Dd>, #fbits
12340      are of this form.  We only handle a subset of the cases though.
12341   */
12342   if (BITS8(1,1,1,0,1,0,1,1) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,1))
12343       && BITS4(1,0,1,0) == (INSN(19,16) & BITS4(1,0,1,0))
12344       && BITS3(1,0,1) == INSN(11,9)
12345       && BITS3(1,0,0) == (INSN(6,4) & BITS3(1,0,1))) {
12346      UInt bD   = INSN(22,22);
12347      UInt bOP  = INSN(18,18);
12348      UInt bU   = INSN(16,16);
12349      UInt Vd   = INSN(15,12);
12350      UInt bSF  = INSN(8,8);
12351      UInt bSX  = INSN(7,7);
12352      UInt bI   = INSN(5,5);
12353      UInt imm4 = INSN(3,0);
12354      Bool to_fixed = bOP == 1;
12355      Bool dp_op    = bSF == 1;
12356      Bool unsyned = bU == 1;
12357      UInt size = bSX == 0 ? 16 : 32;
12358      Int frac_bits = size - ((imm4 << 1) | bI);
12359      UInt d = dp_op  ? ((bD << 4) | Vd)  : ((Vd << 1) | bD);
12360      if (frac_bits >= 1 && frac_bits <= 32 && !to_fixed && size == 32) {
12361         /* dp_op == 0 : VCVT.F32.{S,U}32 S[d], S[d], #frac_bits */
12362         /* dp_op == 1 : VCVT.F64.{S,U}32 D[d], D[d], #frac_bits */
12363         /* This generates really horrible code.  We could potentially
12364            do much better. */
12365         IRTemp rmode = newTemp(Ity_I32);
12366         assign(rmode, mkU32(Irrm_NEAREST)); // rmode that this insn is defd to use
12367         IRTemp src32 = newTemp(Ity_I32);
12368         if (dp_op == 0) {
12369            assign(src32,  unop(Iop_ReinterpF32asI32, getFReg(d)));
12370         } else {
12371            /* Example code sequence of using vcvt.f64.s32. The s32 value is
12372               initialized in s14 but loaded via d7 (s14 is the low half of
12373               d7), so we need to decode the register using getDReg instead of
12374               getFReg. Since the conversion size is from s32 to f64, we also
12375               need to explicitly extract the low half of i64 here.
12376
12377               81a0:       ee07 2a10       vmov            s14, r2
12378               81a4:       eeba 7bef       vcvt.f64.s32    d7, d7, #1
12379             */
12380            IRTemp src64 = newTemp(Ity_I64);
12381            assign(src64,  unop(Iop_ReinterpF64asI64, getDReg(d)));
12382            assign(src32, unop(Iop_64to32, mkexpr(src64)));
12383         }
12384         IRExpr* as_F64 = unop( unsyned ? Iop_I32UtoF64 : Iop_I32StoF64,
12385                                mkexpr(src32 ) );
12386         IRTemp scale = newTemp(Ity_F64);
12387         assign(scale, unop(Iop_I32UtoF64, mkU32( 1 << (frac_bits-1) )));
12388         IRExpr* rm     = mkU32(Irrm_NEAREST);
12389         IRExpr* resF64 = triop(Iop_DivF64,
12390                                rm, as_F64,
12391                                triop(Iop_AddF64, rm, mkexpr(scale), mkexpr(scale)));
12392         if (dp_op == 0) {
12393            IRExpr* resF32 = binop(Iop_F64toF32, mkexpr(rmode), resF64);
12394            putFReg(d, resF32, condT);
12395            DIP("vcvt.f32.%c32, s%u, s%u, #%d\n",
12396                unsyned ? 'u' : 's', d, d, frac_bits);
12397         } else {
12398            putDReg(d, resF64, condT);
12399            DIP("vcvt.f64.%c32, d%u, d%u, #%d\n",
12400                unsyned ? 'u' : 's', d, d, frac_bits);
12401         }
12402         goto decode_success_vfp;
12403      }
12404      /* fall through */
12405   }
12406
12407   /* FAILURE */
12408   return False;
12409
12410  decode_success_vfp:
12411   /* Check that any accepted insn really is a CP10 or CP11 insn, iow,
12412      assert that we aren't accepting, in this fn, insns that actually
12413      should be handled somewhere else. */
12414   vassert(INSN(11,9) == BITS3(1,0,1)); // 11:8 = 1010 or 1011
12415   return True;
12416
12417#  undef INSN
12418}
12419
12420
12421/*------------------------------------------------------------*/
12422/*--- Instructions in NV (never) space                     ---*/
12423/*------------------------------------------------------------*/
12424
12425/* ARM only */
12426/* Translate a NV space instruction.  If successful, returns True and
12427   *dres may or may not be updated.  If failure, returns False and
12428   doesn't change *dres nor create any IR.
12429
12430   Note that all NEON instructions (in ARM mode) are handled through
12431   here, since they are all in NV space.
12432*/
12433static Bool decode_NV_instruction ( /*MOD*/DisResult* dres,
12434                                    VexArchInfo* archinfo,
12435                                    UInt insn )
12436{
12437#  define INSN(_bMax,_bMin)  SLICE_UInt(insn, (_bMax), (_bMin))
12438#  define INSN_COND          SLICE_UInt(insn, 31, 28)
12439
12440   HChar dis_buf[128];
12441
12442   // Should only be called for NV instructions
12443   vassert(BITS4(1,1,1,1) == INSN_COND);
12444
12445   /* ------------------------ pld ------------------------ */
12446   if (BITS8(0,1,0,1, 0, 1,0,1) == (INSN(27,20) & BITS8(1,1,1,1,0,1,1,1))
12447       && BITS4(1,1,1,1) == INSN(15,12)) {
12448      UInt rN    = INSN(19,16);
12449      UInt imm12 = INSN(11,0);
12450      UInt bU    = INSN(23,23);
12451      DIP("pld [r%u, #%c%u]\n", rN, bU ? '+' : '-', imm12);
12452      return True;
12453   }
12454
12455   if (BITS8(0,1,1,1, 0, 1,0,1) == (INSN(27,20) & BITS8(1,1,1,1,0,1,1,1))
12456       && BITS4(1,1,1,1) == INSN(15,12)
12457       && 0 == INSN(4,4)) {
12458      UInt rN   = INSN(19,16);
12459      UInt rM   = INSN(3,0);
12460      UInt imm5 = INSN(11,7);
12461      UInt sh2  = INSN(6,5);
12462      UInt bU   = INSN(23,23);
12463      if (rM != 15) {
12464         IRExpr* eaE = mk_EA_reg_plusminus_shifted_reg(rN, bU, rM,
12465                                                       sh2, imm5, dis_buf);
12466         IRTemp eaT = newTemp(Ity_I32);
12467         /* Bind eaE to a temp merely for debugging-vex purposes, so we
12468            can check it's a plausible decoding.  It will get removed
12469            by iropt a little later on. */
12470         vassert(eaE);
12471         assign(eaT, eaE);
12472         DIP("pld %s\n", dis_buf);
12473         return True;
12474      }
12475      /* fall through */
12476   }
12477
12478   /* ------------------------ pli ------------------------ */
12479   if (BITS8(0,1,0,0, 0, 1,0,1) == (INSN(27,20) & BITS8(1,1,1,1,0,1,1,1))
12480       && BITS4(1,1,1,1) == INSN(15,12)) {
12481      UInt rN    = INSN(19,16);
12482      UInt imm12 = INSN(11,0);
12483      UInt bU    = INSN(23,23);
12484      DIP("pli [r%u, #%c%u]\n", rN, bU ? '+' : '-', imm12);
12485      return True;
12486   }
12487
12488   /* --------------------- Interworking branches --------------------- */
12489
12490   // BLX (1), viz, unconditional branch and link to R15+simm24
12491   // and set CPSR.T = 1, that is, switch to Thumb mode
12492   if (INSN(31,25) == BITS7(1,1,1,1,1,0,1)) {
12493      UInt bitH   = INSN(24,24);
12494      Int  uimm24 = INSN(23,0);
12495      Int  simm24 = (((uimm24 << 8) >> 8) << 2) + (bitH << 1);
12496      /* Now this is a bit tricky.  Since we're decoding an ARM insn,
12497         it is implies that CPSR.T == 0.  Hence the current insn's
12498         address is guaranteed to be of the form X--(30)--X00.  So, no
12499         need to mask any bits off it.  But need to set the lowest bit
12500         to 1 to denote we're in Thumb mode after this, since
12501         guest_R15T has CPSR.T as the lowest bit.  And we can't chase
12502         into the call, so end the block at this point. */
12503      UInt dst = guest_R15_curr_instr_notENC + 8 + (simm24 | 1);
12504      putIRegA( 14, mkU32(guest_R15_curr_instr_notENC + 4),
12505                    IRTemp_INVALID/*because AL*/, Ijk_Boring );
12506      llPutIReg(15, mkU32(dst));
12507      dres->jk_StopHere = Ijk_Call;
12508      dres->whatNext    = Dis_StopHere;
12509      DIP("blx 0x%x (and switch to Thumb mode)\n", dst - 1);
12510      return True;
12511   }
12512
12513   /* ------------------- v7 barrier insns ------------------- */
12514   switch (insn) {
12515      case 0xF57FF06F: /* ISB */
12516         stmt( IRStmt_MBE(Imbe_Fence) );
12517         DIP("ISB\n");
12518         return True;
12519      case 0xF57FF04F: /* DSB sy */
12520      case 0xF57FF04E: /* DSB st */
12521      case 0xF57FF04B: /* DSB ish */
12522      case 0xF57FF04A: /* DSB ishst */
12523      case 0xF57FF047: /* DSB nsh */
12524      case 0xF57FF046: /* DSB nshst */
12525      case 0xF57FF043: /* DSB osh */
12526      case 0xF57FF042: /* DSB oshst */
12527         stmt( IRStmt_MBE(Imbe_Fence) );
12528         DIP("DSB\n");
12529         return True;
12530      case 0xF57FF05F: /* DMB sy */
12531      case 0xF57FF05E: /* DMB st */
12532      case 0xF57FF05B: /* DMB ish */
12533      case 0xF57FF05A: /* DMB ishst */
12534      case 0xF57FF057: /* DMB nsh */
12535      case 0xF57FF056: /* DMB nshst */
12536      case 0xF57FF053: /* DMB osh */
12537      case 0xF57FF052: /* DMB oshst */
12538         stmt( IRStmt_MBE(Imbe_Fence) );
12539         DIP("DMB\n");
12540         return True;
12541      default:
12542         break;
12543   }
12544
12545   /* ------------------- CLREX ------------------ */
12546   if (insn == 0xF57FF01F) {
12547      /* AFAICS, this simply cancels a (all?) reservations made by a
12548         (any?) preceding LDREX(es).  Arrange to hand it through to
12549         the back end. */
12550      stmt( IRStmt_MBE(Imbe_CancelReservation) );
12551      DIP("clrex\n");
12552      return True;
12553   }
12554
12555   /* ------------------- NEON ------------------- */
12556   if (archinfo->hwcaps & VEX_HWCAPS_ARM_NEON) {
12557      Bool ok_neon = decode_NEON_instruction(
12558                        dres, insn, IRTemp_INVALID/*unconditional*/,
12559                        False/*!isT*/
12560                     );
12561      if (ok_neon)
12562         return True;
12563   }
12564
12565   // unrecognised
12566   return False;
12567
12568#  undef INSN_COND
12569#  undef INSN
12570}
12571
12572
12573/*------------------------------------------------------------*/
12574/*--- Disassemble a single ARM instruction                 ---*/
12575/*------------------------------------------------------------*/
12576
12577/* Disassemble a single ARM instruction into IR.  The instruction is
12578   located in host memory at guest_instr, and has (decoded) guest IP
12579   of guest_R15_curr_instr_notENC, which will have been set before the
12580   call here. */
12581
12582static
12583DisResult disInstr_ARM_WRK (
12584             Bool         (*resteerOkFn) ( /*opaque*/void*, Addr64 ),
12585             Bool         resteerCisOk,
12586             void*        callback_opaque,
12587             UChar*       guest_instr,
12588             VexArchInfo* archinfo,
12589             VexAbiInfo*  abiinfo
12590          )
12591{
12592   // A macro to fish bits out of 'insn'.
12593#  define INSN(_bMax,_bMin)  SLICE_UInt(insn, (_bMax), (_bMin))
12594#  define INSN_COND          SLICE_UInt(insn, 31, 28)
12595
12596   DisResult dres;
12597   UInt      insn;
12598   //Bool      allow_VFP = False;
12599   //UInt      hwcaps = archinfo->hwcaps;
12600   IRTemp    condT; /* :: Ity_I32 */
12601   UInt      summary;
12602   HChar     dis_buf[128];  // big enough to hold LDMIA etc text
12603
12604   /* What insn variants are we supporting today? */
12605   //allow_VFP  = (0 != (hwcaps & VEX_HWCAPS_ARM_VFP));
12606   // etc etc
12607
12608   /* Set result defaults. */
12609   dres.whatNext    = Dis_Continue;
12610   dres.len         = 4;
12611   dres.continueAt  = 0;
12612   dres.jk_StopHere = Ijk_INVALID;
12613
12614   /* Set default actions for post-insn handling of writes to r15, if
12615      required. */
12616   r15written = False;
12617   r15guard   = IRTemp_INVALID; /* unconditional */
12618   r15kind    = Ijk_Boring;
12619
12620   /* At least this is simple on ARM: insns are all 4 bytes long, and
12621      4-aligned.  So just fish the whole thing out of memory right now
12622      and have done. */
12623   insn = getUIntLittleEndianly( guest_instr );
12624
12625   if (0) vex_printf("insn: 0x%x\n", insn);
12626
12627   DIP("\t(arm) 0x%x:  ", (UInt)guest_R15_curr_instr_notENC);
12628
12629   vassert(0 == (guest_R15_curr_instr_notENC & 3));
12630
12631   /* ----------------------------------------------------------- */
12632
12633   /* Spot "Special" instructions (see comment at top of file). */
12634   {
12635      UChar* code = (UChar*)guest_instr;
12636      /* Spot the 16-byte preamble:
12637
12638         e1a0c1ec  mov r12, r12, ROR #3
12639         e1a0c6ec  mov r12, r12, ROR #13
12640         e1a0ceec  mov r12, r12, ROR #29
12641         e1a0c9ec  mov r12, r12, ROR #19
12642      */
12643      UInt word1 = 0xE1A0C1EC;
12644      UInt word2 = 0xE1A0C6EC;
12645      UInt word3 = 0xE1A0CEEC;
12646      UInt word4 = 0xE1A0C9EC;
12647      if (getUIntLittleEndianly(code+ 0) == word1 &&
12648          getUIntLittleEndianly(code+ 4) == word2 &&
12649          getUIntLittleEndianly(code+ 8) == word3 &&
12650          getUIntLittleEndianly(code+12) == word4) {
12651         /* Got a "Special" instruction preamble.  Which one is it? */
12652         if (getUIntLittleEndianly(code+16) == 0xE18AA00A
12653                                               /* orr r10,r10,r10 */) {
12654            /* R3 = client_request ( R4 ) */
12655            DIP("r3 = client_request ( %%r4 )\n");
12656            llPutIReg(15, mkU32( guest_R15_curr_instr_notENC + 20 ));
12657            dres.jk_StopHere = Ijk_ClientReq;
12658            dres.whatNext    = Dis_StopHere;
12659            goto decode_success;
12660         }
12661         else
12662         if (getUIntLittleEndianly(code+16) == 0xE18BB00B
12663                                               /* orr r11,r11,r11 */) {
12664            /* R3 = guest_NRADDR */
12665            DIP("r3 = guest_NRADDR\n");
12666            dres.len = 20;
12667            llPutIReg(3, IRExpr_Get( OFFB_NRADDR, Ity_I32 ));
12668            goto decode_success;
12669         }
12670         else
12671         if (getUIntLittleEndianly(code+16) == 0xE18CC00C
12672                                               /* orr r12,r12,r12 */) {
12673            /*  branch-and-link-to-noredir R4 */
12674            DIP("branch-and-link-to-noredir r4\n");
12675            llPutIReg(14, mkU32( guest_R15_curr_instr_notENC + 20) );
12676            llPutIReg(15, llGetIReg(4));
12677            dres.jk_StopHere = Ijk_NoRedir;
12678            dres.whatNext    = Dis_StopHere;
12679            goto decode_success;
12680         }
12681         /* We don't know what it is.  Set opc1/opc2 so decode_failure
12682            can print the insn following the Special-insn preamble. */
12683         insn = getUIntLittleEndianly(code+16);
12684         goto decode_failure;
12685         /*NOTREACHED*/
12686      }
12687
12688   }
12689
12690   /* ----------------------------------------------------------- */
12691
12692   /* Main ARM instruction decoder starts here. */
12693
12694   /* Deal with the condition.  Strategy is to merely generate a
12695      condition temporary at this point (or IRTemp_INVALID, meaning
12696      unconditional).  We leave it to lower-level instruction decoders
12697      to decide whether they can generate straight-line code, or
12698      whether they must generate a side exit before the instruction.
12699      condT :: Ity_I32 and is always either zero or one. */
12700   condT = IRTemp_INVALID;
12701   switch ( (ARMCondcode)INSN_COND ) {
12702      case ARMCondNV: {
12703         // Illegal instruction prior to v5 (see ARM ARM A3-5), but
12704         // some cases are acceptable
12705         Bool ok = decode_NV_instruction(&dres, archinfo, insn);
12706         if (ok)
12707            goto decode_success;
12708         else
12709            goto decode_failure;
12710      }
12711      case ARMCondAL: // Always executed
12712         break;
12713      case ARMCondEQ: case ARMCondNE: case ARMCondHS: case ARMCondLO:
12714      case ARMCondMI: case ARMCondPL: case ARMCondVS: case ARMCondVC:
12715      case ARMCondHI: case ARMCondLS: case ARMCondGE: case ARMCondLT:
12716      case ARMCondGT: case ARMCondLE:
12717         condT = newTemp(Ity_I32);
12718         assign( condT, mk_armg_calculate_condition( INSN_COND ));
12719         break;
12720   }
12721
12722   /* ----------------------------------------------------------- */
12723   /* -- ARMv5 integer instructions                            -- */
12724   /* ----------------------------------------------------------- */
12725
12726   /* ---------------- Data processing ops ------------------- */
12727
12728   if (0 == (INSN(27,20) & BITS8(1,1,0,0,0,0,0,0))
12729       && !(INSN(25,25) == 0 && INSN(7,7) == 1 && INSN(4,4) == 1)) {
12730      IRTemp  shop = IRTemp_INVALID; /* shifter operand */
12731      IRTemp  shco = IRTemp_INVALID; /* shifter carry out */
12732      UInt    rD   = (insn >> 12) & 0xF; /* 15:12 */
12733      UInt    rN   = (insn >> 16) & 0xF; /* 19:16 */
12734      UInt    bitS = (insn >> 20) & 1; /* 20:20 */
12735      IRTemp  rNt  = IRTemp_INVALID;
12736      IRTemp  res  = IRTemp_INVALID;
12737      IRTemp  oldV = IRTemp_INVALID;
12738      IRTemp  oldC = IRTemp_INVALID;
12739      HChar*  name = NULL;
12740      IROp    op   = Iop_INVALID;
12741      Bool    ok;
12742
12743      switch (INSN(24,21)) {
12744
12745         /* --------- ADD, SUB, AND, OR --------- */
12746         case BITS4(0,1,0,0): /* ADD:  Rd = Rn + shifter_operand */
12747            name = "add"; op = Iop_Add32; goto rd_eq_rn_op_SO;
12748         case BITS4(0,0,1,0): /* SUB:  Rd = Rn - shifter_operand */
12749            name = "sub"; op = Iop_Sub32; goto rd_eq_rn_op_SO;
12750         case BITS4(0,0,1,1): /* RSB:  Rd = shifter_operand - Rn */
12751            name = "rsb"; op = Iop_Sub32; goto rd_eq_rn_op_SO;
12752         case BITS4(0,0,0,0): /* AND:  Rd = Rn & shifter_operand */
12753            name = "and"; op = Iop_And32; goto rd_eq_rn_op_SO;
12754         case BITS4(1,1,0,0): /* OR:   Rd = Rn | shifter_operand */
12755            name = "orr"; op = Iop_Or32; goto rd_eq_rn_op_SO;
12756         case BITS4(0,0,0,1): /* EOR:  Rd = Rn ^ shifter_operand */
12757            name = "eor"; op = Iop_Xor32; goto rd_eq_rn_op_SO;
12758         case BITS4(1,1,1,0): /* BIC:  Rd = Rn & ~shifter_operand */
12759            name = "bic"; op = Iop_And32; goto rd_eq_rn_op_SO;
12760         rd_eq_rn_op_SO: {
12761            Bool isRSB = False;
12762            Bool isBIC = False;
12763            switch (INSN(24,21)) {
12764               case BITS4(0,0,1,1):
12765                  vassert(op == Iop_Sub32); isRSB = True; break;
12766               case BITS4(1,1,1,0):
12767                  vassert(op == Iop_And32); isBIC = True; break;
12768               default:
12769                  break;
12770            }
12771            rNt = newTemp(Ity_I32);
12772            assign(rNt, getIRegA(rN));
12773            ok = mk_shifter_operand(
12774                    INSN(25,25), INSN(11,0),
12775                    &shop, bitS ? &shco : NULL, dis_buf
12776                 );
12777            if (!ok)
12778               break;
12779            res = newTemp(Ity_I32);
12780            // compute the main result
12781            if (isRSB) {
12782               // reverse-subtract: shifter_operand - Rn
12783               vassert(op == Iop_Sub32);
12784               assign(res, binop(op, mkexpr(shop), mkexpr(rNt)) );
12785            } else if (isBIC) {
12786               // andn: shifter_operand & ~Rn
12787               vassert(op == Iop_And32);
12788               assign(res, binop(op, mkexpr(rNt),
12789                                     unop(Iop_Not32, mkexpr(shop))) );
12790            } else {
12791               // normal: Rn op shifter_operand
12792               assign(res, binop(op, mkexpr(rNt), mkexpr(shop)) );
12793            }
12794            // but don't commit it until after we've finished
12795            // all necessary reads from the guest state
12796            if (bitS
12797                && (op == Iop_And32 || op == Iop_Or32 || op == Iop_Xor32)) {
12798               oldV = newTemp(Ity_I32);
12799               assign( oldV, mk_armg_calculate_flag_v() );
12800            }
12801            // can't safely read guest state after here
12802            // now safe to put the main result
12803            putIRegA( rD, mkexpr(res), condT, Ijk_Boring );
12804            // XXXX!! not safe to read any guest state after
12805            // this point (I think the code below doesn't do that).
12806            if (!bitS)
12807               vassert(shco == IRTemp_INVALID);
12808            /* Update the flags thunk if necessary */
12809            if (bitS) {
12810               vassert(shco != IRTemp_INVALID);
12811               switch (op) {
12812                  case Iop_Add32:
12813                     setFlags_D1_D2( ARMG_CC_OP_ADD, rNt, shop, condT );
12814                     break;
12815                  case Iop_Sub32:
12816                     if (isRSB) {
12817                        setFlags_D1_D2( ARMG_CC_OP_SUB, shop, rNt, condT );
12818                     } else {
12819                        setFlags_D1_D2( ARMG_CC_OP_SUB, rNt, shop, condT );
12820                     }
12821                     break;
12822                  case Iop_And32: /* BIC and AND set the flags the same */
12823                  case Iop_Or32:
12824                  case Iop_Xor32:
12825                     // oldV has been read just above
12826                     setFlags_D1_D2_ND( ARMG_CC_OP_LOGIC,
12827                                        res, shco, oldV, condT );
12828                     break;
12829                  default:
12830                     vassert(0);
12831               }
12832            }
12833            DIP("%s%s%s r%u, r%u, %s\n",
12834                name, nCC(INSN_COND), bitS ? "s" : "", rD, rN, dis_buf );
12835            goto decode_success;
12836         }
12837
12838         /* --------- MOV, MVN --------- */
12839         case BITS4(1,1,0,1):   /* MOV: Rd = shifter_operand */
12840         case BITS4(1,1,1,1): { /* MVN: Rd = not(shifter_operand) */
12841            Bool isMVN = INSN(24,21) == BITS4(1,1,1,1);
12842            IRTemp jk = Ijk_Boring;
12843            if (rN != 0)
12844               break; /* rN must be zero */
12845            ok = mk_shifter_operand(
12846                    INSN(25,25), INSN(11,0),
12847                    &shop, bitS ? &shco : NULL, dis_buf
12848                 );
12849            if (!ok)
12850               break;
12851            res = newTemp(Ity_I32);
12852            assign( res, isMVN ? unop(Iop_Not32, mkexpr(shop))
12853                               : mkexpr(shop) );
12854            if (bitS) {
12855               vassert(shco != IRTemp_INVALID);
12856               oldV = newTemp(Ity_I32);
12857               assign( oldV, mk_armg_calculate_flag_v() );
12858            } else {
12859               vassert(shco == IRTemp_INVALID);
12860            }
12861            /* According to the Cortex A8 TRM Sec. 5.2.1, MOV PC, r14 is a
12862                return for purposes of branch prediction. */
12863            if (!isMVN && INSN(11,0) == 14) {
12864              jk = Ijk_Ret;
12865            }
12866            // can't safely read guest state after here
12867            putIRegA( rD, mkexpr(res), condT, jk );
12868            /* Update the flags thunk if necessary */
12869            if (bitS) {
12870               setFlags_D1_D2_ND( ARMG_CC_OP_LOGIC,
12871                                  res, shco, oldV, condT );
12872            }
12873            DIP("%s%s%s r%u, %s\n",
12874                isMVN ? "mvn" : "mov",
12875                nCC(INSN_COND), bitS ? "s" : "", rD, dis_buf );
12876            goto decode_success;
12877         }
12878
12879         /* --------- CMP --------- */
12880         case BITS4(1,0,1,0):   /* CMP:  (void) Rn - shifter_operand */
12881         case BITS4(1,0,1,1): { /* CMN:  (void) Rn + shifter_operand */
12882            Bool isCMN = INSN(24,21) == BITS4(1,0,1,1);
12883            if (rD != 0)
12884               break; /* rD must be zero */
12885            if (bitS == 0)
12886               break; /* if S (bit 20) is not set, it's not CMP/CMN */
12887            rNt = newTemp(Ity_I32);
12888            assign(rNt, getIRegA(rN));
12889            ok = mk_shifter_operand(
12890                    INSN(25,25), INSN(11,0),
12891                    &shop, NULL, dis_buf
12892                 );
12893            if (!ok)
12894               break;
12895            // can't safely read guest state after here
12896            /* Update the flags thunk. */
12897            setFlags_D1_D2( isCMN ? ARMG_CC_OP_ADD : ARMG_CC_OP_SUB,
12898                            rNt, shop, condT );
12899            DIP("%s%s r%u, %s\n",
12900                isCMN ? "cmn" : "cmp",
12901                nCC(INSN_COND), rN, dis_buf );
12902            goto decode_success;
12903         }
12904
12905         /* --------- TST --------- */
12906         case BITS4(1,0,0,0):   /* TST:  (void) Rn & shifter_operand */
12907         case BITS4(1,0,0,1): { /* TEQ:  (void) Rn ^ shifter_operand */
12908            Bool isTEQ = INSN(24,21) == BITS4(1,0,0,1);
12909            if (rD != 0)
12910               break; /* rD must be zero */
12911            if (bitS == 0)
12912               break; /* if S (bit 20) is not set, it's not TST/TEQ */
12913            rNt = newTemp(Ity_I32);
12914            assign(rNt, getIRegA(rN));
12915            ok = mk_shifter_operand(
12916                    INSN(25,25), INSN(11,0),
12917                    &shop, &shco, dis_buf
12918                 );
12919            if (!ok)
12920               break;
12921            /* Update the flags thunk. */
12922            res = newTemp(Ity_I32);
12923            assign( res, binop(isTEQ ? Iop_Xor32 : Iop_And32,
12924                               mkexpr(rNt), mkexpr(shop)) );
12925            oldV = newTemp(Ity_I32);
12926            assign( oldV, mk_armg_calculate_flag_v() );
12927            // can't safely read guest state after here
12928            setFlags_D1_D2_ND( ARMG_CC_OP_LOGIC,
12929                               res, shco, oldV, condT );
12930            DIP("%s%s r%u, %s\n",
12931                isTEQ ? "teq" : "tst",
12932                nCC(INSN_COND), rN, dis_buf );
12933            goto decode_success;
12934         }
12935
12936         /* --------- ADC, SBC, RSC --------- */
12937         case BITS4(0,1,0,1): /* ADC:  Rd = Rn + shifter_operand + oldC */
12938            name = "adc"; goto rd_eq_rn_op_SO_op_oldC;
12939         case BITS4(0,1,1,0): /* SBC:  Rd = Rn - shifter_operand - (oldC ^ 1) */
12940            name = "sbc"; goto rd_eq_rn_op_SO_op_oldC;
12941         case BITS4(0,1,1,1): /* RSC:  Rd = shifter_operand - Rn - (oldC ^ 1) */
12942            name = "rsc"; goto rd_eq_rn_op_SO_op_oldC;
12943         rd_eq_rn_op_SO_op_oldC: {
12944            // FIXME: shco isn't used for anything.  Get rid of it.
12945            rNt = newTemp(Ity_I32);
12946            assign(rNt, getIRegA(rN));
12947            ok = mk_shifter_operand(
12948                    INSN(25,25), INSN(11,0),
12949                    &shop, bitS ? &shco : NULL, dis_buf
12950                 );
12951            if (!ok)
12952               break;
12953            oldC = newTemp(Ity_I32);
12954            assign( oldC, mk_armg_calculate_flag_c() );
12955            res = newTemp(Ity_I32);
12956            // compute the main result
12957            switch (INSN(24,21)) {
12958               case BITS4(0,1,0,1): /* ADC */
12959                  assign(res,
12960                         binop(Iop_Add32,
12961                               binop(Iop_Add32, mkexpr(rNt), mkexpr(shop)),
12962                               mkexpr(oldC) ));
12963                  break;
12964               case BITS4(0,1,1,0): /* SBC */
12965                  assign(res,
12966                         binop(Iop_Sub32,
12967                               binop(Iop_Sub32, mkexpr(rNt), mkexpr(shop)),
12968                               binop(Iop_Xor32, mkexpr(oldC), mkU32(1)) ));
12969                  break;
12970               case BITS4(0,1,1,1): /* RSC */
12971                  assign(res,
12972                         binop(Iop_Sub32,
12973                               binop(Iop_Sub32, mkexpr(shop), mkexpr(rNt)),
12974                               binop(Iop_Xor32, mkexpr(oldC), mkU32(1)) ));
12975                  break;
12976               default:
12977                  vassert(0);
12978            }
12979            // but don't commit it until after we've finished
12980            // all necessary reads from the guest state
12981            // now safe to put the main result
12982            putIRegA( rD, mkexpr(res), condT, Ijk_Boring );
12983            // XXXX!! not safe to read any guest state after
12984            // this point (I think the code below doesn't do that).
12985            if (!bitS)
12986               vassert(shco == IRTemp_INVALID);
12987            /* Update the flags thunk if necessary */
12988            if (bitS) {
12989               vassert(shco != IRTemp_INVALID);
12990               switch (INSN(24,21)) {
12991                  case BITS4(0,1,0,1): /* ADC */
12992                     setFlags_D1_D2_ND( ARMG_CC_OP_ADC,
12993                                        rNt, shop, oldC, condT );
12994                     break;
12995                  case BITS4(0,1,1,0): /* SBC */
12996                     setFlags_D1_D2_ND( ARMG_CC_OP_SBB,
12997                                        rNt, shop, oldC, condT );
12998                     break;
12999                  case BITS4(0,1,1,1): /* RSC */
13000                     setFlags_D1_D2_ND( ARMG_CC_OP_SBB,
13001                                        shop, rNt, oldC, condT );
13002                     break;
13003                  default:
13004                     vassert(0);
13005               }
13006            }
13007            DIP("%s%s%s r%u, r%u, %s\n",
13008                name, nCC(INSN_COND), bitS ? "s" : "", rD, rN, dis_buf );
13009            goto decode_success;
13010         }
13011
13012         /* --------- ??? --------- */
13013         default:
13014            break;
13015      }
13016   } /* if (0 == (INSN(27,20) & BITS8(1,1,0,0,0,0,0,0)) */
13017
13018   /* --------------------- Load/store (ubyte & word) -------- */
13019   // LDR STR LDRB STRB
13020   /*                 31   27   23   19 15 11    6   4 3  # highest bit
13021                        28   24   20 16 12
13022      A5-20   1 | 16  cond 0101 UB0L Rn Rd imm12
13023      A5-22   1 | 32  cond 0111 UBOL Rn Rd imm5  sh2 0 Rm
13024      A5-24   2 | 16  cond 0101 UB1L Rn Rd imm12
13025      A5-26   2 | 32  cond 0111 UB1L Rn Rd imm5  sh2 0 Rm
13026      A5-28   3 | 16  cond 0100 UB0L Rn Rd imm12
13027      A5-32   3 | 32  cond 0110 UB0L Rn Rd imm5  sh2 0 Rm
13028   */
13029   /* case coding:
13030             1   at-ea               (access at ea)
13031             2   at-ea-then-upd      (access at ea, then Rn = ea)
13032             3   at-Rn-then-upd      (access at Rn, then Rn = ea)
13033      ea coding
13034             16  Rn +/- imm12
13035             32  Rn +/- Rm sh2 imm5
13036   */
13037   /* Quickly skip over all of this for hopefully most instructions */
13038   if ((INSN(27,24) & BITS4(1,1,0,0)) != BITS4(0,1,0,0))
13039      goto after_load_store_ubyte_or_word;
13040
13041   summary = 0;
13042
13043   /**/ if (INSN(27,24) == BITS4(0,1,0,1) && INSN(21,21) == 0) {
13044      summary = 1 | 16;
13045   }
13046   else if (INSN(27,24) == BITS4(0,1,1,1) && INSN(21,21) == 0
13047                                          && INSN(4,4) == 0) {
13048      summary = 1 | 32;
13049   }
13050   else if (INSN(27,24) == BITS4(0,1,0,1) && INSN(21,21) == 1) {
13051      summary = 2 | 16;
13052   }
13053   else if (INSN(27,24) == BITS4(0,1,1,1) && INSN(21,21) == 1
13054                                          && INSN(4,4) == 0) {
13055      summary = 2 | 32;
13056   }
13057   else if (INSN(27,24) == BITS4(0,1,0,0) && INSN(21,21) == 0) {
13058      summary = 3 | 16;
13059   }
13060   else if (INSN(27,24) == BITS4(0,1,1,0) && INSN(21,21) == 0
13061                                          && INSN(4,4) == 0) {
13062      summary = 3 | 32;
13063   }
13064   else goto after_load_store_ubyte_or_word;
13065
13066   { UInt rN = (insn >> 16) & 0xF; /* 19:16 */
13067     UInt rD = (insn >> 12) & 0xF; /* 15:12 */
13068     UInt rM = (insn >> 0)  & 0xF; /*  3:0  */
13069     UInt bU = (insn >> 23) & 1;      /* 23 */
13070     UInt bB = (insn >> 22) & 1;      /* 22 */
13071     UInt bL = (insn >> 20) & 1;      /* 20 */
13072     UInt imm12 = (insn >> 0) & 0xFFF; /* 11:0 */
13073     UInt imm5  = (insn >> 7) & 0x1F;  /* 11:7 */
13074     UInt sh2   = (insn >> 5) & 3;     /* 6:5 */
13075
13076     /* Skip some invalid cases, which would lead to two competing
13077        updates to the same register, or which are otherwise
13078        disallowed by the spec. */
13079     switch (summary) {
13080        case 1 | 16:
13081           break;
13082        case 1 | 32:
13083           if (rM == 15) goto after_load_store_ubyte_or_word;
13084           break;
13085        case 2 | 16: case 3 | 16:
13086           if (rN == 15) goto after_load_store_ubyte_or_word;
13087           if (bL == 1 && rN == rD) goto after_load_store_ubyte_or_word;
13088           break;
13089        case 2 | 32: case 3 | 32:
13090           if (rM == 15) goto after_load_store_ubyte_or_word;
13091           if (rN == 15) goto after_load_store_ubyte_or_word;
13092           if (rN == rM) goto after_load_store_ubyte_or_word;
13093           if (bL == 1 && rN == rD) goto after_load_store_ubyte_or_word;
13094           break;
13095        default:
13096           vassert(0);
13097     }
13098
13099     /* Now, we can't do a conditional load or store, since that very
13100        likely will generate an exception.  So we have to take a side
13101        exit at this point if the condition is false. */
13102     if (condT != IRTemp_INVALID) {
13103        mk_skip_over_A32_if_cond_is_false( condT );
13104        condT = IRTemp_INVALID;
13105     }
13106     /* Ok, now we're unconditional.  Do the load or store. */
13107
13108     /* compute the effective address.  Bind it to a tmp since we
13109        may need to use it twice. */
13110     IRExpr* eaE = NULL;
13111     switch (summary & 0xF0) {
13112        case 16:
13113           eaE = mk_EA_reg_plusminus_imm12( rN, bU, imm12, dis_buf );
13114           break;
13115        case 32:
13116           eaE = mk_EA_reg_plusminus_shifted_reg( rN, bU, rM, sh2, imm5,
13117                                                  dis_buf );
13118           break;
13119     }
13120     vassert(eaE);
13121     IRTemp eaT = newTemp(Ity_I32);
13122     assign(eaT, eaE);
13123
13124     /* get the old Rn value */
13125     IRTemp rnT = newTemp(Ity_I32);
13126     assign(rnT, getIRegA(rN));
13127
13128     /* decide on the transfer address */
13129     IRTemp taT = IRTemp_INVALID;
13130     switch (summary & 0x0F) {
13131        case 1: case 2: taT = eaT; break;
13132        case 3:         taT = rnT; break;
13133     }
13134     vassert(taT != IRTemp_INVALID);
13135
13136     if (bL == 0) {
13137       /* Store.  If necessary, update the base register before the
13138          store itself, so that the common idiom of "str rX, [sp,
13139          #-4]!" (store rX at sp-4, then do new sp = sp-4, a.k.a "push
13140          rX") doesn't cause Memcheck to complain that the access is
13141          below the stack pointer.  Also, not updating sp before the
13142          store confuses Valgrind's dynamic stack-extending logic.  So
13143          do it before the store.  Hence we need to snarf the store
13144          data before doing the basereg update. */
13145
13146        /* get hold of the data to be stored */
13147        IRTemp rDt = newTemp(Ity_I32);
13148        assign(rDt, getIRegA(rD));
13149
13150        /* Update Rn if necessary. */
13151        switch (summary & 0x0F) {
13152           case 2: case 3:
13153              putIRegA( rN, mkexpr(eaT), IRTemp_INVALID, Ijk_Boring );
13154              break;
13155        }
13156
13157        /* generate the transfer */
13158        if (bB == 0) { // word store
13159           storeLE( mkexpr(taT), mkexpr(rDt) );
13160        } else { // byte store
13161           vassert(bB == 1);
13162           storeLE( mkexpr(taT), unop(Iop_32to8, mkexpr(rDt)) );
13163        }
13164
13165     } else {
13166        /* Load */
13167        vassert(bL == 1);
13168
13169        /* generate the transfer */
13170        if (bB == 0) { // word load
13171           IRTemp jk = Ijk_Boring;
13172           /* According to the Cortex A8 TRM Sec. 5.2.1, LDR(1) with r13 as the
13173               base register and PC as the destination register is a return for
13174               purposes of branch prediction.
13175              The ARM ARM Sec. C9.10.1 further specifies that it must use a
13176               post-increment by immediate addressing mode to be counted in
13177               event 0x0E (Procedure return).*/
13178           if (rN == 13 && summary == (3 | 16) && bB == 0) {
13179              jk = Ijk_Ret;
13180           }
13181           putIRegA( rD, loadLE(Ity_I32, mkexpr(taT)),
13182                     IRTemp_INVALID, jk );
13183        } else { // byte load
13184           vassert(bB == 1);
13185           putIRegA( rD, unop(Iop_8Uto32, loadLE(Ity_I8, mkexpr(taT))),
13186                     IRTemp_INVALID, Ijk_Boring );
13187        }
13188
13189        /* Update Rn if necessary. */
13190        switch (summary & 0x0F) {
13191           case 2: case 3:
13192              // should be assured by logic above:
13193              if (bL == 1)
13194                 vassert(rD != rN); /* since we just wrote rD */
13195              putIRegA( rN, mkexpr(eaT), IRTemp_INVALID, Ijk_Boring );
13196              break;
13197        }
13198     }
13199
13200     switch (summary & 0x0F) {
13201        case 1:  DIP("%sr%s%s r%u, %s\n",
13202                     bL == 0 ? "st" : "ld",
13203                     bB == 0 ? "" : "b", nCC(INSN_COND), rD, dis_buf);
13204                 break;
13205        case 2:  DIP("%sr%s%s r%u, %s! (at-EA-then-Rn=EA)\n",
13206                     bL == 0 ? "st" : "ld",
13207                     bB == 0 ? "" : "b", nCC(INSN_COND), rD, dis_buf);
13208                 break;
13209        case 3:  DIP("%sr%s%s r%u, %s! (at-Rn-then-Rn=EA)\n",
13210                     bL == 0 ? "st" : "ld",
13211                     bB == 0 ? "" : "b", nCC(INSN_COND), rD, dis_buf);
13212                 break;
13213        default: vassert(0);
13214     }
13215
13216     /* XXX deal with alignment constraints */
13217
13218     goto decode_success;
13219
13220     /* Complications:
13221
13222        For all loads: if the Amode specifies base register
13223        writeback, and the same register is specified for Rd and Rn,
13224        the results are UNPREDICTABLE.
13225
13226        For all loads and stores: if R15 is written, branch to
13227        that address afterwards.
13228
13229        STRB: straightforward
13230        LDRB: loaded data is zero extended
13231        STR:  lowest 2 bits of address are ignored
13232        LDR:  if the lowest 2 bits of the address are nonzero
13233              then the loaded value is rotated right by 8 * the lowest 2 bits
13234     */
13235   }
13236
13237  after_load_store_ubyte_or_word:
13238
13239   /* --------------------- Load/store (sbyte & hword) -------- */
13240   // LDRH LDRSH STRH LDRSB
13241   /*                 31   27   23   19 15 11   7    3     # highest bit
13242                        28   24   20 16 12    8    4    0
13243      A5-36   1 | 16  cond 0001 U10L Rn Rd im4h 1SH1 im4l
13244      A5-38   1 | 32  cond 0001 U00L Rn Rd 0000 1SH1 Rm
13245      A5-40   2 | 16  cond 0001 U11L Rn Rd im4h 1SH1 im4l
13246      A5-42   2 | 32  cond 0001 U01L Rn Rd 0000 1SH1 Rm
13247      A5-44   3 | 16  cond 0000 U10L Rn Rd im4h 1SH1 im4l
13248      A5-46   3 | 32  cond 0000 U00L Rn Rd 0000 1SH1 Rm
13249   */
13250   /* case coding:
13251             1   at-ea               (access at ea)
13252             2   at-ea-then-upd      (access at ea, then Rn = ea)
13253             3   at-Rn-then-upd      (access at Rn, then Rn = ea)
13254      ea coding
13255             16  Rn +/- imm8
13256             32  Rn +/- Rm
13257   */
13258   /* Quickly skip over all of this for hopefully most instructions */
13259   if ((INSN(27,24) & BITS4(1,1,1,0)) != BITS4(0,0,0,0))
13260      goto after_load_store_sbyte_or_hword;
13261
13262   /* Check the "1SH1" thing. */
13263   if ((INSN(7,4) & BITS4(1,0,0,1)) != BITS4(1,0,0,1))
13264      goto after_load_store_sbyte_or_hword;
13265
13266   summary = 0;
13267
13268   /**/ if (INSN(27,24) == BITS4(0,0,0,1) && INSN(22,21) == BITS2(1,0)) {
13269      summary = 1 | 16;
13270   }
13271   else if (INSN(27,24) == BITS4(0,0,0,1) && INSN(22,21) == BITS2(0,0)) {
13272      summary = 1 | 32;
13273   }
13274   else if (INSN(27,24) == BITS4(0,0,0,1) && INSN(22,21) == BITS2(1,1)) {
13275      summary = 2 | 16;
13276   }
13277   else if (INSN(27,24) == BITS4(0,0,0,1) && INSN(22,21) == BITS2(0,1)) {
13278      summary = 2 | 32;
13279   }
13280   else if (INSN(27,24) == BITS4(0,0,0,0) && INSN(22,21) == BITS2(1,0)) {
13281      summary = 3 | 16;
13282   }
13283   else if (INSN(27,24) == BITS4(0,0,0,0) && INSN(22,21) == BITS2(0,0)) {
13284      summary = 3 | 32;
13285   }
13286   else goto after_load_store_sbyte_or_hword;
13287
13288   { UInt rN   = (insn >> 16) & 0xF; /* 19:16 */
13289     UInt rD   = (insn >> 12) & 0xF; /* 15:12 */
13290     UInt rM   = (insn >> 0)  & 0xF; /*  3:0  */
13291     UInt bU   = (insn >> 23) & 1;   /* 23 U=1 offset+, U=0 offset- */
13292     UInt bL   = (insn >> 20) & 1;   /* 20 L=1 load, L=0 store */
13293     UInt bH   = (insn >> 5) & 1;    /* H=1 halfword, H=0 byte */
13294     UInt bS   = (insn >> 6) & 1;    /* S=1 signed, S=0 unsigned */
13295     UInt imm8 = ((insn >> 4) & 0xF0) | (insn & 0xF); /* 11:8, 3:0 */
13296
13297     /* Skip combinations that are either meaningless or already
13298        handled by main word-or-unsigned-byte load-store
13299        instructions. */
13300     if (bS == 0 && bH == 0) /* "unsigned byte" */
13301        goto after_load_store_sbyte_or_hword;
13302     if (bS == 1 && bL == 0) /* "signed store" */
13303        goto after_load_store_sbyte_or_hword;
13304
13305     /* Require 11:8 == 0 for Rn +/- Rm cases */
13306     if ((summary & 32) != 0 && (imm8 & 0xF0) != 0)
13307        goto after_load_store_sbyte_or_hword;
13308
13309     /* Skip some invalid cases, which would lead to two competing
13310        updates to the same register, or which are otherwise
13311        disallowed by the spec. */
13312     switch (summary) {
13313        case 1 | 16:
13314           break;
13315        case 1 | 32:
13316           if (rM == 15) goto after_load_store_sbyte_or_hword;
13317           break;
13318        case 2 | 16: case 3 | 16:
13319           if (rN == 15) goto after_load_store_sbyte_or_hword;
13320           if (bL == 1 && rN == rD) goto after_load_store_sbyte_or_hword;
13321           break;
13322        case 2 | 32: case 3 | 32:
13323           if (rM == 15) goto after_load_store_sbyte_or_hword;
13324           if (rN == 15) goto after_load_store_sbyte_or_hword;
13325           if (rN == rM) goto after_load_store_sbyte_or_hword;
13326           if (bL == 1 && rN == rD) goto after_load_store_sbyte_or_hword;
13327           break;
13328        default:
13329           vassert(0);
13330     }
13331
13332     /* Now, we can't do a conditional load or store, since that very
13333        likely will generate an exception.  So we have to take a side
13334        exit at this point if the condition is false. */
13335     if (condT != IRTemp_INVALID) {
13336        mk_skip_over_A32_if_cond_is_false( condT );
13337        condT = IRTemp_INVALID;
13338     }
13339     /* Ok, now we're unconditional.  Do the load or store. */
13340
13341     /* compute the effective address.  Bind it to a tmp since we
13342        may need to use it twice. */
13343     IRExpr* eaE = NULL;
13344     switch (summary & 0xF0) {
13345        case 16:
13346           eaE = mk_EA_reg_plusminus_imm8( rN, bU, imm8, dis_buf );
13347           break;
13348        case 32:
13349           eaE = mk_EA_reg_plusminus_reg( rN, bU, rM, dis_buf );
13350           break;
13351     }
13352     vassert(eaE);
13353     IRTemp eaT = newTemp(Ity_I32);
13354     assign(eaT, eaE);
13355
13356     /* get the old Rn value */
13357     IRTemp rnT = newTemp(Ity_I32);
13358     assign(rnT, getIRegA(rN));
13359
13360     /* decide on the transfer address */
13361     IRTemp taT = IRTemp_INVALID;
13362     switch (summary & 0x0F) {
13363        case 1: case 2: taT = eaT; break;
13364        case 3:         taT = rnT; break;
13365     }
13366     vassert(taT != IRTemp_INVALID);
13367
13368     /* halfword store  H 1  L 0  S 0
13369        uhalf load      H 1  L 1  S 0
13370        shalf load      H 1  L 1  S 1
13371        sbyte load      H 0  L 1  S 1
13372     */
13373     HChar* name = NULL;
13374     /* generate the transfer */
13375     /**/ if (bH == 1 && bL == 0 && bS == 0) { // halfword store
13376        storeLE( mkexpr(taT), unop(Iop_32to16, getIRegA(rD)) );
13377        name = "strh";
13378     }
13379     else if (bH == 1 && bL == 1 && bS == 0) { // uhalf load
13380        putIRegA( rD, unop(Iop_16Uto32, loadLE(Ity_I16, mkexpr(taT))),
13381                  IRTemp_INVALID, Ijk_Boring );
13382        name = "ldrh";
13383     }
13384     else if (bH == 1 && bL == 1 && bS == 1) { // shalf load
13385        putIRegA( rD, unop(Iop_16Sto32, loadLE(Ity_I16, mkexpr(taT))),
13386                  IRTemp_INVALID, Ijk_Boring );
13387        name = "ldrsh";
13388     }
13389     else if (bH == 0 && bL == 1 && bS == 1) { // sbyte load
13390        putIRegA( rD, unop(Iop_8Sto32, loadLE(Ity_I8, mkexpr(taT))),
13391                  IRTemp_INVALID, Ijk_Boring );
13392        name = "ldrsb";
13393     }
13394     else
13395        vassert(0); // should be assured by logic above
13396
13397     /* Update Rn if necessary. */
13398     switch (summary & 0x0F) {
13399        case 2: case 3:
13400           // should be assured by logic above:
13401           if (bL == 1)
13402              vassert(rD != rN); /* since we just wrote rD */
13403           putIRegA( rN, mkexpr(eaT), IRTemp_INVALID, Ijk_Boring );
13404           break;
13405     }
13406
13407     switch (summary & 0x0F) {
13408        case 1:  DIP("%s%s r%u, %s\n", name, nCC(INSN_COND), rD, dis_buf);
13409                 break;
13410        case 2:  DIP("%s%s r%u, %s! (at-EA-then-Rn=EA)\n",
13411                     name, nCC(INSN_COND), rD, dis_buf);
13412                 break;
13413        case 3:  DIP("%s%s r%u, %s! (at-Rn-then-Rn=EA)\n",
13414                     name, nCC(INSN_COND), rD, dis_buf);
13415                 break;
13416        default: vassert(0);
13417     }
13418
13419     /* XXX deal with alignment constraints */
13420
13421     goto decode_success;
13422
13423     /* Complications:
13424
13425        For all loads: if the Amode specifies base register
13426        writeback, and the same register is specified for Rd and Rn,
13427        the results are UNPREDICTABLE.
13428
13429        For all loads and stores: if R15 is written, branch to
13430        that address afterwards.
13431
13432        Misaligned halfword stores => Unpredictable
13433        Misaligned halfword loads  => Unpredictable
13434     */
13435   }
13436
13437  after_load_store_sbyte_or_hword:
13438
13439   /* --------------------- Load/store multiple -------------- */
13440   // LD/STMIA LD/STMIB LD/STMDA LD/STMDB
13441   // Remarkably complex and difficult to get right
13442   // match 27:20 as 100XX0WL
13443   if (BITS8(1,0,0,0,0,0,0,0) == (INSN(27,20) & BITS8(1,1,1,0,0,1,0,0))) {
13444      // A5-50 LD/STMIA  cond 1000 10WL Rn RegList
13445      // A5-51 LD/STMIB  cond 1001 10WL Rn RegList
13446      // A5-53 LD/STMDA  cond 1000 00WL Rn RegList
13447      // A5-53 LD/STMDB  cond 1001 00WL Rn RegList
13448      //                   28   24   20 16       0
13449
13450      UInt bINC    = (insn >> 23) & 1;
13451      UInt bBEFORE = (insn >> 24) & 1;
13452
13453      UInt bL      = (insn >> 20) & 1;  /* load=1, store=0 */
13454      UInt bW      = (insn >> 21) & 1;  /* Rn wback=1, no wback=0 */
13455      UInt rN      = (insn >> 16) & 0xF;
13456      UInt regList = insn & 0xFFFF;
13457      /* Skip some invalid cases, which would lead to two competing
13458         updates to the same register, or which are otherwise
13459         disallowed by the spec.  Note the test above has required
13460         that S == 0, since that looks like a kernel-mode only thing.
13461         Done by forcing the real pattern, viz 100XXSWL to actually be
13462         100XX0WL. */
13463      if (rN == 15) goto after_load_store_multiple;
13464      // reglist can't be empty
13465      if (regList == 0) goto after_load_store_multiple;
13466      // if requested to writeback Rn, and this is a load instruction,
13467      // then Rn can't appear in RegList, since we'd have two competing
13468      // new values for Rn.  We do however accept this case for store
13469      // instructions.
13470      if (bW == 1 && bL == 1 && ((1 << rN) & regList) > 0)
13471         goto after_load_store_multiple;
13472
13473      /* Now, we can't do a conditional load or store, since that very
13474         likely will generate an exception.  So we have to take a side
13475         exit at this point if the condition is false. */
13476      if (condT != IRTemp_INVALID) {
13477         mk_skip_over_A32_if_cond_is_false( condT );
13478         condT = IRTemp_INVALID;
13479      }
13480
13481      /* Ok, now we're unconditional.  Generate the IR. */
13482      mk_ldm_stm( True/*arm*/, rN, bINC, bBEFORE, bW, bL, regList );
13483
13484      DIP("%sm%c%c%s r%u%s, {0x%04x}\n",
13485          bL == 1 ? "ld" : "st", bINC ? 'i' : 'd', bBEFORE ? 'b' : 'a',
13486          nCC(INSN_COND),
13487          rN, bW ? "!" : "", regList);
13488
13489      goto decode_success;
13490   }
13491
13492  after_load_store_multiple:
13493
13494   /* --------------------- Control flow --------------------- */
13495   // B, BL (Branch, or Branch-and-Link, to immediate offset)
13496   //
13497   if (BITS8(1,0,1,0,0,0,0,0) == (INSN(27,20) & BITS8(1,1,1,0,0,0,0,0))) {
13498      UInt link   = (insn >> 24) & 1;
13499      UInt uimm24 = insn & ((1<<24)-1);
13500      Int  simm24 = (Int)uimm24;
13501      UInt dst    = guest_R15_curr_instr_notENC + 8
13502                    + (((simm24 << 8) >> 8) << 2);
13503      IRJumpKind jk = link ? Ijk_Call : Ijk_Boring;
13504      if (link) {
13505         putIRegA(14, mkU32(guest_R15_curr_instr_notENC + 4),
13506                      condT, Ijk_Boring);
13507      }
13508      if (condT == IRTemp_INVALID) {
13509         /* unconditional transfer to 'dst'.  See if we can simply
13510            continue tracing at the destination. */
13511         if (resteerOkFn( callback_opaque, (Addr64)dst )) {
13512            /* yes */
13513            dres.whatNext   = Dis_ResteerU;
13514            dres.continueAt = (Addr64)dst;
13515         } else {
13516            /* no; terminate the SB at this point. */
13517            llPutIReg(15, mkU32(dst));
13518            dres.jk_StopHere = jk;
13519            dres.whatNext    = Dis_StopHere;
13520         }
13521         DIP("b%s 0x%x\n", link ? "l" : "", dst);
13522      } else {
13523         /* conditional transfer to 'dst' */
13524         HChar* comment = "";
13525
13526         /* First see if we can do some speculative chasing into one
13527            arm or the other.  Be conservative and only chase if
13528            !link, that is, this is a normal conditional branch to a
13529            known destination. */
13530         if (!link
13531             && resteerCisOk
13532             && vex_control.guest_chase_cond
13533             && dst < guest_R15_curr_instr_notENC
13534             && resteerOkFn( callback_opaque, (Addr64)(Addr32)dst) ) {
13535            /* Speculation: assume this backward branch is taken.  So
13536               we need to emit a side-exit to the insn following this
13537               one, on the negation of the condition, and continue at
13538               the branch target address (dst). */
13539            stmt( IRStmt_Exit( unop(Iop_Not1,
13540                                    unop(Iop_32to1, mkexpr(condT))),
13541                               Ijk_Boring,
13542                               IRConst_U32(guest_R15_curr_instr_notENC+4),
13543                               OFFB_R15T ));
13544            dres.whatNext   = Dis_ResteerC;
13545            dres.continueAt = (Addr64)(Addr32)dst;
13546            comment = "(assumed taken)";
13547         }
13548         else
13549         if (!link
13550             && resteerCisOk
13551             && vex_control.guest_chase_cond
13552             && dst >= guest_R15_curr_instr_notENC
13553             && resteerOkFn( callback_opaque,
13554                             (Addr64)(Addr32)
13555                                     (guest_R15_curr_instr_notENC+4)) ) {
13556            /* Speculation: assume this forward branch is not taken.
13557               So we need to emit a side-exit to dst (the dest) and
13558               continue disassembling at the insn immediately
13559               following this one. */
13560            stmt( IRStmt_Exit( unop(Iop_32to1, mkexpr(condT)),
13561                               Ijk_Boring,
13562                               IRConst_U32(dst),
13563                               OFFB_R15T ));
13564            dres.whatNext   = Dis_ResteerC;
13565            dres.continueAt = (Addr64)(Addr32)
13566                                      (guest_R15_curr_instr_notENC+4);
13567            comment = "(assumed not taken)";
13568         }
13569         else {
13570            /* Conservative default translation - end the block at
13571               this point. */
13572            stmt( IRStmt_Exit( unop(Iop_32to1, mkexpr(condT)),
13573                               jk, IRConst_U32(dst), OFFB_R15T ));
13574            llPutIReg(15, mkU32(guest_R15_curr_instr_notENC + 4));
13575            dres.jk_StopHere = Ijk_Boring;
13576            dres.whatNext    = Dis_StopHere;
13577         }
13578         DIP("b%s%s 0x%x %s\n", link ? "l" : "", nCC(INSN_COND),
13579             dst, comment);
13580      }
13581      goto decode_success;
13582   }
13583
13584   // B, BL (Branch, or Branch-and-Link, to a register)
13585   // NB: interworking branch
13586   if (INSN(27,20) == BITS8(0,0,0,1,0,0,1,0)
13587       && INSN(19,12) == BITS8(1,1,1,1,1,1,1,1)
13588       && (INSN(11,4) == BITS8(1,1,1,1,0,0,1,1)
13589           || INSN(11,4) == BITS8(1,1,1,1,0,0,0,1))) {
13590      IRTemp  dst = newTemp(Ity_I32);
13591      UInt    link = (INSN(11,4) >> 1) & 1;
13592      UInt    rM   = INSN(3,0);
13593      // we don't decode the case (link && rM == 15), as that's
13594      // Unpredictable.
13595      if (!(link && rM == 15)) {
13596         if (condT != IRTemp_INVALID) {
13597            mk_skip_over_A32_if_cond_is_false( condT );
13598         }
13599         // rM contains an interworking address exactly as we require
13600         // (with continuation CPSR.T in bit 0), so we can use it
13601         // as-is, with no masking.
13602         assign( dst, getIRegA(rM) );
13603         if (link) {
13604            putIRegA( 14, mkU32(guest_R15_curr_instr_notENC + 4),
13605                      IRTemp_INVALID/*because AL*/, Ijk_Boring );
13606         }
13607         llPutIReg(15, mkexpr(dst));
13608         dres.jk_StopHere = link ? Ijk_Call
13609                                 : (rM == 14 ? Ijk_Ret : Ijk_Boring);
13610         dres.whatNext    = Dis_StopHere;
13611         if (condT == IRTemp_INVALID) {
13612            DIP("b%sx r%u\n", link ? "l" : "", rM);
13613         } else {
13614            DIP("b%sx%s r%u\n", link ? "l" : "", nCC(INSN_COND), rM);
13615         }
13616         goto decode_success;
13617      }
13618      /* else: (link && rM == 15): just fall through */
13619   }
13620
13621   /* --- NB: ARM interworking branches are in NV space, hence
13622      are handled elsewhere by decode_NV_instruction.
13623      ---
13624   */
13625
13626   /* --------------------- Clz --------------------- */
13627   // CLZ
13628   if (INSN(27,20) == BITS8(0,0,0,1,0,1,1,0)
13629       && INSN(19,16) == BITS4(1,1,1,1)
13630       && INSN(11,4) == BITS8(1,1,1,1,0,0,0,1)) {
13631      UInt rD = INSN(15,12);
13632      UInt rM = INSN(3,0);
13633      IRTemp arg = newTemp(Ity_I32);
13634      IRTemp res = newTemp(Ity_I32);
13635      assign(arg, getIRegA(rM));
13636      assign(res, IRExpr_Mux0X(
13637                     unop(Iop_1Uto8,binop(Iop_CmpEQ32, mkexpr(arg),
13638                                                       mkU32(0))),
13639                     unop(Iop_Clz32, mkexpr(arg)),
13640                     mkU32(32)
13641            ));
13642      putIRegA(rD, mkexpr(res), condT, Ijk_Boring);
13643      DIP("clz%s r%u, r%u\n", nCC(INSN_COND), rD, rM);
13644      goto decode_success;
13645   }
13646
13647   /* --------------------- Mul etc --------------------- */
13648   // MUL
13649   if (BITS8(0,0,0,0,0,0,0,0) == (INSN(27,20) & BITS8(1,1,1,1,1,1,1,0))
13650       && INSN(15,12) == BITS4(0,0,0,0)
13651       && INSN(7,4) == BITS4(1,0,0,1)) {
13652      UInt bitS = (insn >> 20) & 1; /* 20:20 */
13653      UInt rD = INSN(19,16);
13654      UInt rS = INSN(11,8);
13655      UInt rM = INSN(3,0);
13656      if (rD == 15 || rM == 15 || rS == 15) {
13657         /* Unpredictable; don't decode; fall through */
13658      } else {
13659         IRTemp argL = newTemp(Ity_I32);
13660         IRTemp argR = newTemp(Ity_I32);
13661         IRTemp res  = newTemp(Ity_I32);
13662         IRTemp oldC = IRTemp_INVALID;
13663         IRTemp oldV = IRTemp_INVALID;
13664         assign( argL, getIRegA(rM));
13665         assign( argR, getIRegA(rS));
13666         assign( res, binop(Iop_Mul32, mkexpr(argL), mkexpr(argR)) );
13667         if (bitS) {
13668            oldC = newTemp(Ity_I32);
13669            assign(oldC, mk_armg_calculate_flag_c());
13670            oldV = newTemp(Ity_I32);
13671            assign(oldV, mk_armg_calculate_flag_v());
13672         }
13673         // now update guest state
13674         putIRegA( rD, mkexpr(res), condT, Ijk_Boring );
13675         if (bitS) {
13676            IRTemp pair = newTemp(Ity_I32);
13677            assign( pair, binop(Iop_Or32,
13678                                binop(Iop_Shl32, mkexpr(oldC), mkU8(1)),
13679                                mkexpr(oldV)) );
13680            setFlags_D1_ND( ARMG_CC_OP_MUL, res, pair, condT );
13681         }
13682         DIP("mul%c%s r%u, r%u, r%u\n",
13683             bitS ? 's' : ' ', nCC(INSN_COND), rD, rM, rS);
13684         goto decode_success;
13685      }
13686      /* fall through */
13687   }
13688
13689   /* --------------------- Integer Divides --------------------- */
13690   // SDIV
13691   if (BITS8(0,1,1,1,0,0,0,1) == INSN(27,20)
13692       && INSN(15,12) == BITS4(1,1,1,1)
13693       && INSN(7,4) == BITS4(0,0,0,1)) {
13694      UInt rD = INSN(19,16);
13695      UInt rM = INSN(11,8);
13696      UInt rN = INSN(3,0);
13697      if (rD == 15 || rM == 15 || rN == 15) {
13698         /* Unpredictable; don't decode; fall through */
13699      } else {
13700         IRTemp res = newTemp(Ity_I32);
13701         IRTemp argL  = newTemp(Ity_I32);
13702         IRTemp argR  = newTemp(Ity_I32);
13703         assign(argL, getIRegA(rN));
13704         assign(argR, getIRegA(rM));
13705         assign(res, binop(Iop_DivS32, mkexpr(argL), mkexpr(argR)));
13706         putIRegA(rD, mkexpr(res), condT, Ijk_Boring);
13707         DIP("sdiv r%u, r%u, r%u\n", rD, rN, rM);
13708         goto decode_success;
13709      }
13710    }
13711
13712   // UDIV
13713   if (BITS8(0,1,1,1,0,0,1,1) == INSN(27,20)
13714       && INSN(15,12) == BITS4(1,1,1,1)
13715       && INSN(7,4) == BITS4(0,0,0,1)) {
13716      UInt rD = INSN(19,16);
13717      UInt rM = INSN(11,8);
13718      UInt rN = INSN(3,0);
13719      if (rD == 15 || rM == 15 || rN == 15) {
13720         /* Unpredictable; don't decode; fall through */
13721      } else {
13722         IRTemp res = newTemp(Ity_I32);
13723         IRTemp argL  = newTemp(Ity_I32);
13724         IRTemp argR  = newTemp(Ity_I32);
13725         assign(argL, getIRegA(rN));
13726         assign(argR, getIRegA(rM));
13727         assign(res, binop(Iop_DivU32, mkexpr(argL), mkexpr(argR)));
13728         putIRegA(rD, mkexpr(res), condT, Ijk_Boring);
13729         DIP("udiv r%u, r%u, r%u\n", rD, rN, rM);
13730         goto decode_success;
13731      }
13732    }
13733
13734   // MLA, MLS
13735   if (BITS8(0,0,0,0,0,0,1,0) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,0))
13736       && INSN(7,4) == BITS4(1,0,0,1)) {
13737      UInt bitS  = (insn >> 20) & 1; /* 20:20 */
13738      UInt isMLS = (insn >> 22) & 1; /* 22:22 */
13739      UInt rD = INSN(19,16);
13740      UInt rN = INSN(15,12);
13741      UInt rS = INSN(11,8);
13742      UInt rM = INSN(3,0);
13743      if (bitS == 1 && isMLS == 1) {
13744         /* This isn't allowed (MLS that sets flags).  don't decode;
13745            fall through */
13746      }
13747      else
13748      if (rD == 15 || rM == 15 || rS == 15 || rN == 15) {
13749         /* Unpredictable; don't decode; fall through */
13750      } else {
13751         IRTemp argL = newTemp(Ity_I32);
13752         IRTemp argR = newTemp(Ity_I32);
13753         IRTemp argP = newTemp(Ity_I32);
13754         IRTemp res  = newTemp(Ity_I32);
13755         IRTemp oldC = IRTemp_INVALID;
13756         IRTemp oldV = IRTemp_INVALID;
13757         assign( argL, getIRegA(rM));
13758         assign( argR, getIRegA(rS));
13759         assign( argP, getIRegA(rN));
13760         assign( res, binop(isMLS ? Iop_Sub32 : Iop_Add32,
13761                            mkexpr(argP),
13762                            binop(Iop_Mul32, mkexpr(argL), mkexpr(argR)) ));
13763         if (bitS) {
13764            vassert(!isMLS); // guaranteed above
13765            oldC = newTemp(Ity_I32);
13766            assign(oldC, mk_armg_calculate_flag_c());
13767            oldV = newTemp(Ity_I32);
13768            assign(oldV, mk_armg_calculate_flag_v());
13769         }
13770         // now update guest state
13771         putIRegA( rD, mkexpr(res), condT, Ijk_Boring );
13772         if (bitS) {
13773            IRTemp pair = newTemp(Ity_I32);
13774            assign( pair, binop(Iop_Or32,
13775                                binop(Iop_Shl32, mkexpr(oldC), mkU8(1)),
13776                                mkexpr(oldV)) );
13777            setFlags_D1_ND( ARMG_CC_OP_MUL, res, pair, condT );
13778         }
13779         DIP("ml%c%c%s r%u, r%u, r%u, r%u\n",
13780             isMLS ? 's' : 'a', bitS ? 's' : ' ',
13781             nCC(INSN_COND), rD, rM, rS, rN);
13782         goto decode_success;
13783      }
13784      /* fall through */
13785   }
13786
13787   // SMULL, UMULL
13788   if (BITS8(0,0,0,0,1,0,0,0) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,0))
13789       && INSN(7,4) == BITS4(1,0,0,1)) {
13790      UInt bitS = (insn >> 20) & 1; /* 20:20 */
13791      UInt rDhi = INSN(19,16);
13792      UInt rDlo = INSN(15,12);
13793      UInt rS   = INSN(11,8);
13794      UInt rM   = INSN(3,0);
13795      UInt isS  = (INSN(27,20) >> 2) & 1; /* 22:22 */
13796      if (rDhi == 15 || rDlo == 15 || rM == 15 || rS == 15 || rDhi == rDlo)  {
13797         /* Unpredictable; don't decode; fall through */
13798      } else {
13799         IRTemp argL  = newTemp(Ity_I32);
13800         IRTemp argR  = newTemp(Ity_I32);
13801         IRTemp res   = newTemp(Ity_I64);
13802         IRTemp resHi = newTemp(Ity_I32);
13803         IRTemp resLo = newTemp(Ity_I32);
13804         IRTemp oldC  = IRTemp_INVALID;
13805         IRTemp oldV  = IRTemp_INVALID;
13806         IROp   mulOp = isS ? Iop_MullS32 : Iop_MullU32;
13807         assign( argL, getIRegA(rM));
13808         assign( argR, getIRegA(rS));
13809         assign( res, binop(mulOp, mkexpr(argL), mkexpr(argR)) );
13810         assign( resHi, unop(Iop_64HIto32, mkexpr(res)) );
13811         assign( resLo, unop(Iop_64to32, mkexpr(res)) );
13812         if (bitS) {
13813            oldC = newTemp(Ity_I32);
13814            assign(oldC, mk_armg_calculate_flag_c());
13815            oldV = newTemp(Ity_I32);
13816            assign(oldV, mk_armg_calculate_flag_v());
13817         }
13818         // now update guest state
13819         putIRegA( rDhi, mkexpr(resHi), condT, Ijk_Boring );
13820         putIRegA( rDlo, mkexpr(resLo), condT, Ijk_Boring );
13821         if (bitS) {
13822            IRTemp pair = newTemp(Ity_I32);
13823            assign( pair, binop(Iop_Or32,
13824                                binop(Iop_Shl32, mkexpr(oldC), mkU8(1)),
13825                                mkexpr(oldV)) );
13826            setFlags_D1_D2_ND( ARMG_CC_OP_MULL, resLo, resHi, pair, condT );
13827         }
13828         DIP("%cmull%c%s r%u, r%u, r%u, r%u\n",
13829             isS ? 's' : 'u', bitS ? 's' : ' ',
13830             nCC(INSN_COND), rDlo, rDhi, rM, rS);
13831         goto decode_success;
13832      }
13833      /* fall through */
13834   }
13835
13836   // SMLAL, UMLAL
13837   if (BITS8(0,0,0,0,1,0,1,0) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,0))
13838       && INSN(7,4) == BITS4(1,0,0,1)) {
13839      UInt bitS = (insn >> 20) & 1; /* 20:20 */
13840      UInt rDhi = INSN(19,16);
13841      UInt rDlo = INSN(15,12);
13842      UInt rS   = INSN(11,8);
13843      UInt rM   = INSN(3,0);
13844      UInt isS  = (INSN(27,20) >> 2) & 1; /* 22:22 */
13845      if (rDhi == 15 || rDlo == 15 || rM == 15 || rS == 15 || rDhi == rDlo)  {
13846         /* Unpredictable; don't decode; fall through */
13847      } else {
13848         IRTemp argL  = newTemp(Ity_I32);
13849         IRTemp argR  = newTemp(Ity_I32);
13850         IRTemp old   = newTemp(Ity_I64);
13851         IRTemp res   = newTemp(Ity_I64);
13852         IRTemp resHi = newTemp(Ity_I32);
13853         IRTemp resLo = newTemp(Ity_I32);
13854         IRTemp oldC  = IRTemp_INVALID;
13855         IRTemp oldV  = IRTemp_INVALID;
13856         IROp   mulOp = isS ? Iop_MullS32 : Iop_MullU32;
13857         assign( argL, getIRegA(rM));
13858         assign( argR, getIRegA(rS));
13859         assign( old, binop(Iop_32HLto64, getIRegA(rDhi), getIRegA(rDlo)) );
13860         assign( res, binop(Iop_Add64,
13861                            mkexpr(old),
13862                            binop(mulOp, mkexpr(argL), mkexpr(argR))) );
13863         assign( resHi, unop(Iop_64HIto32, mkexpr(res)) );
13864         assign( resLo, unop(Iop_64to32, mkexpr(res)) );
13865         if (bitS) {
13866            oldC = newTemp(Ity_I32);
13867            assign(oldC, mk_armg_calculate_flag_c());
13868            oldV = newTemp(Ity_I32);
13869            assign(oldV, mk_armg_calculate_flag_v());
13870         }
13871         // now update guest state
13872         putIRegA( rDhi, mkexpr(resHi), condT, Ijk_Boring );
13873         putIRegA( rDlo, mkexpr(resLo), condT, Ijk_Boring );
13874         if (bitS) {
13875            IRTemp pair = newTemp(Ity_I32);
13876            assign( pair, binop(Iop_Or32,
13877                                binop(Iop_Shl32, mkexpr(oldC), mkU8(1)),
13878                                mkexpr(oldV)) );
13879            setFlags_D1_D2_ND( ARMG_CC_OP_MULL, resLo, resHi, pair, condT );
13880         }
13881         DIP("%cmlal%c%s r%u, r%u, r%u, r%u\n",
13882             isS ? 's' : 'u', bitS ? 's' : ' ', nCC(INSN_COND),
13883             rDlo, rDhi, rM, rS);
13884         goto decode_success;
13885      }
13886      /* fall through */
13887   }
13888
13889   /* --------------------- Msr etc --------------------- */
13890
13891   // MSR apsr, #imm
13892   if (INSN(27,20) == BITS8(0,0,1,1,0,0,1,0)
13893       && INSN(17,12) == BITS6(0,0,1,1,1,1)) {
13894      UInt write_ge    = INSN(18,18);
13895      UInt write_nzcvq = INSN(19,19);
13896      if (write_nzcvq || write_ge) {
13897         UInt   imm = (INSN(11,0) >> 0) & 0xFF;
13898         UInt   rot = 2 * ((INSN(11,0) >> 8) & 0xF);
13899         IRTemp immT = newTemp(Ity_I32);
13900         vassert(rot <= 30);
13901         imm = ROR32(imm, rot);
13902         assign(immT, mkU32(imm));
13903         desynthesise_APSR( write_nzcvq, write_ge, immT, condT );
13904         DIP("msr%s cpsr%s%sf, #0x%08x\n", nCC(INSN_COND),
13905             write_nzcvq ? "f" : "", write_ge ? "g" : "", imm);
13906         goto decode_success;
13907      }
13908      /* fall through */
13909   }
13910
13911   // MSR apsr, reg
13912   if (INSN(27,20) == BITS8(0,0,0,1,0,0,1,0)
13913       && INSN(17,12) == BITS6(0,0,1,1,1,1)
13914       && INSN(11,4) == BITS8(0,0,0,0,0,0,0,0)) {
13915      UInt rN          = INSN(3,0);
13916      UInt write_ge    = INSN(18,18);
13917      UInt write_nzcvq = INSN(19,19);
13918      if (rN != 15 && (write_nzcvq || write_ge)) {
13919         IRTemp rNt = newTemp(Ity_I32);
13920         assign(rNt, getIRegA(rN));
13921         desynthesise_APSR( write_nzcvq, write_ge, rNt, condT );
13922         DIP("msr%s cpsr_%s%s, r%u\n", nCC(INSN_COND),
13923             write_nzcvq ? "f" : "", write_ge ? "g" : "", rN);
13924         goto decode_success;
13925      }
13926      /* fall through */
13927   }
13928
13929   // MRS rD, cpsr
13930   if ((insn & 0x0FFF0FFF) == 0x010F0000) {
13931      UInt rD   = INSN(15,12);
13932      if (rD != 15) {
13933         IRTemp apsr = synthesise_APSR();
13934         putIRegA( rD, mkexpr(apsr), condT, Ijk_Boring );
13935         DIP("mrs%s r%u, cpsr\n", nCC(INSN_COND), rD);
13936         goto decode_success;
13937      }
13938      /* fall through */
13939   }
13940
13941   /* --------------------- Svc --------------------- */
13942   if (BITS8(1,1,1,1,0,0,0,0) == (INSN(27,20) & BITS8(1,1,1,1,0,0,0,0))) {
13943      UInt imm24 = (insn >> 0) & 0xFFFFFF;
13944      if (imm24 == 0) {
13945         /* A syscall.  We can't do this conditionally, hence: */
13946         if (condT != IRTemp_INVALID) {
13947            mk_skip_over_A32_if_cond_is_false( condT );
13948         }
13949         // AL after here
13950         llPutIReg(15, mkU32( guest_R15_curr_instr_notENC + 4 ));
13951         dres.jk_StopHere = Ijk_Sys_syscall;
13952         dres.whatNext    = Dis_StopHere;
13953         DIP("svc%s #0x%08x\n", nCC(INSN_COND), imm24);
13954         goto decode_success;
13955      }
13956      /* fall through */
13957   }
13958
13959   /* ------------------------ swp ------------------------ */
13960
13961   // SWP, SWPB
13962   if (BITS8(0,0,0,1,0,0,0,0) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,1))
13963       && BITS4(0,0,0,0) == INSN(11,8)
13964       && BITS4(1,0,0,1) == INSN(7,4)) {
13965      UInt   rN   = INSN(19,16);
13966      UInt   rD   = INSN(15,12);
13967      UInt   rM   = INSN(3,0);
13968      IRTemp tRn  = newTemp(Ity_I32);
13969      IRTemp tNew = newTemp(Ity_I32);
13970      IRTemp tOld = IRTemp_INVALID;
13971      IRTemp tSC1 = newTemp(Ity_I1);
13972      UInt   isB  = (insn >> 22) & 1;
13973
13974      if (rD == 15 || rN == 15 || rM == 15 || rN == rM || rN == rD) {
13975         /* undecodable; fall through */
13976      } else {
13977         /* make unconditional */
13978         if (condT != IRTemp_INVALID) {
13979            mk_skip_over_A32_if_cond_is_false( condT );
13980            condT = IRTemp_INVALID;
13981         }
13982         /* Ok, now we're unconditional.  Generate a LL-SC loop. */
13983         assign(tRn, getIRegA(rN));
13984         assign(tNew, getIRegA(rM));
13985         if (isB) {
13986            /* swpb */
13987            tOld = newTemp(Ity_I8);
13988            stmt( IRStmt_LLSC(Iend_LE, tOld, mkexpr(tRn),
13989                              NULL/*=>isLL*/) );
13990            stmt( IRStmt_LLSC(Iend_LE, tSC1, mkexpr(tRn),
13991                              unop(Iop_32to8, mkexpr(tNew))) );
13992         } else {
13993            /* swp */
13994            tOld = newTemp(Ity_I32);
13995            stmt( IRStmt_LLSC(Iend_LE, tOld, mkexpr(tRn),
13996                              NULL/*=>isLL*/) );
13997            stmt( IRStmt_LLSC(Iend_LE, tSC1, mkexpr(tRn),
13998                              mkexpr(tNew)) );
13999         }
14000         stmt( IRStmt_Exit(unop(Iop_Not1, mkexpr(tSC1)),
14001                           /*Ijk_NoRedir*/Ijk_Boring,
14002                           IRConst_U32(guest_R15_curr_instr_notENC),
14003                           OFFB_R15T ));
14004         putIRegA(rD, isB ? unop(Iop_8Uto32, mkexpr(tOld)) : mkexpr(tOld),
14005                      IRTemp_INVALID, Ijk_Boring);
14006         DIP("swp%s%s r%u, r%u, [r%u]\n",
14007             isB ? "b" : "", nCC(INSN_COND), rD, rM, rN);
14008         goto decode_success;
14009      }
14010      /* fall through */
14011   }
14012
14013   /* ----------------------------------------------------------- */
14014   /* -- ARMv6 instructions                                    -- */
14015   /* ----------------------------------------------------------- */
14016
14017   /* ------------------- {ldr,str}ex{,b,h,d} ------------------- */
14018
14019   // LDREXD, LDREX, LDREXH, LDREXB
14020   if (0x01900F9F == (insn & 0x0F900FFF)) {
14021      UInt   rT    = INSN(15,12);
14022      UInt   rN    = INSN(19,16);
14023      IRType ty    = Ity_INVALID;
14024      IROp   widen = Iop_INVALID;
14025      HChar* nm    = NULL;
14026      Bool   valid = True;
14027      switch (INSN(22,21)) {
14028         case 0: nm = "";  ty = Ity_I32; break;
14029         case 1: nm = "d"; ty = Ity_I64; break;
14030         case 2: nm = "b"; ty = Ity_I8;  widen = Iop_8Uto32; break;
14031         case 3: nm = "h"; ty = Ity_I16; widen = Iop_16Uto32; break;
14032         default: vassert(0);
14033      }
14034      if (ty == Ity_I32 || ty == Ity_I16 || ty == Ity_I8) {
14035         if (rT == 15 || rN == 15)
14036            valid = False;
14037      } else {
14038         vassert(ty == Ity_I64);
14039         if ((rT & 1) == 1 || rT == 14 || rN == 15)
14040            valid = False;
14041      }
14042      if (valid) {
14043         IRTemp res;
14044         /* make unconditional */
14045         if (condT != IRTemp_INVALID) {
14046           mk_skip_over_A32_if_cond_is_false( condT );
14047           condT = IRTemp_INVALID;
14048         }
14049         /* Ok, now we're unconditional.  Do the load. */
14050         res = newTemp(ty);
14051         // FIXME: assumes little-endian guest
14052         stmt( IRStmt_LLSC(Iend_LE, res, getIRegA(rN),
14053                           NULL/*this is a load*/) );
14054         if (ty == Ity_I64) {
14055            // FIXME: assumes little-endian guest
14056            putIRegA(rT+0, unop(Iop_64to32, mkexpr(res)),
14057                           IRTemp_INVALID, Ijk_Boring);
14058            putIRegA(rT+1, unop(Iop_64HIto32, mkexpr(res)),
14059                           IRTemp_INVALID, Ijk_Boring);
14060            DIP("ldrex%s%s r%u, r%u, [r%u]\n",
14061                nm, nCC(INSN_COND), rT+0, rT+1, rN);
14062         } else {
14063            putIRegA(rT, widen == Iop_INVALID
14064                            ? mkexpr(res) : unop(widen, mkexpr(res)),
14065                     IRTemp_INVALID, Ijk_Boring);
14066            DIP("ldrex%s%s r%u, [r%u]\n", nm, nCC(INSN_COND), rT, rN);
14067         }
14068         goto decode_success;
14069      }
14070      /* undecodable; fall through */
14071   }
14072
14073   // STREXD, STREX, STREXH, STREXB
14074   if (0x01800F90 == (insn & 0x0F900FF0)) {
14075      UInt   rT     = INSN(3,0);
14076      UInt   rN     = INSN(19,16);
14077      UInt   rD     = INSN(15,12);
14078      IRType ty     = Ity_INVALID;
14079      IROp   narrow = Iop_INVALID;
14080      HChar* nm     = NULL;
14081      Bool   valid  = True;
14082      switch (INSN(22,21)) {
14083         case 0: nm = "";  ty = Ity_I32; break;
14084         case 1: nm = "d"; ty = Ity_I64; break;
14085         case 2: nm = "b"; ty = Ity_I8;  narrow = Iop_32to8; break;
14086         case 3: nm = "h"; ty = Ity_I16; narrow = Iop_32to16; break;
14087         default: vassert(0);
14088      }
14089      if (ty == Ity_I32 || ty == Ity_I16 || ty == Ity_I8) {
14090         if (rD == 15 || rN == 15 || rT == 15
14091             || rD == rN || rD == rT)
14092            valid = False;
14093      } else {
14094         vassert(ty == Ity_I64);
14095         if (rD == 15 || (rT & 1) == 1 || rT == 14 || rN == 15
14096             || rD == rN || rD == rT || rD == rT+1)
14097            valid = False;
14098      }
14099      if (valid) {
14100         IRTemp resSC1, resSC32, data;
14101         /* make unconditional */
14102         if (condT != IRTemp_INVALID) {
14103            mk_skip_over_A32_if_cond_is_false( condT );
14104            condT = IRTemp_INVALID;
14105         }
14106         /* Ok, now we're unconditional.  Do the store. */
14107         data = newTemp(ty);
14108         assign(data,
14109                ty == Ity_I64
14110                   // FIXME: assumes little-endian guest
14111                   ? binop(Iop_32HLto64, getIRegA(rT+1), getIRegA(rT+0))
14112                   : narrow == Iop_INVALID
14113                      ? getIRegA(rT)
14114                      : unop(narrow, getIRegA(rT)));
14115         resSC1 = newTemp(Ity_I1);
14116         // FIXME: assumes little-endian guest
14117         stmt( IRStmt_LLSC(Iend_LE, resSC1, getIRegA(rN), mkexpr(data)) );
14118
14119         /* Set rD to 1 on failure, 0 on success.  Currently we have
14120            resSC1 == 0 on failure, 1 on success. */
14121         resSC32 = newTemp(Ity_I32);
14122         assign(resSC32,
14123                unop(Iop_1Uto32, unop(Iop_Not1, mkexpr(resSC1))));
14124
14125         putIRegA(rD, mkexpr(resSC32),
14126                      IRTemp_INVALID, Ijk_Boring);
14127         if (ty == Ity_I64) {
14128            DIP("strex%s%s r%u, r%u, r%u, [r%u]\n",
14129                nm, nCC(INSN_COND), rD, rT, rT+1, rN);
14130         } else {
14131            DIP("strex%s%s r%u, r%u, [r%u]\n",
14132                nm, nCC(INSN_COND), rD, rT, rN);
14133         }
14134         goto decode_success;
14135      }
14136      /* fall through */
14137   }
14138
14139   /* --------------------- movw, movt --------------------- */
14140   if (0x03000000 == (insn & 0x0FF00000)
14141       || 0x03400000 == (insn & 0x0FF00000)) /* pray for CSE */ {
14142      UInt rD    = INSN(15,12);
14143      UInt imm16 = (insn & 0xFFF) | ((insn >> 4) & 0x0000F000);
14144      UInt isT   = (insn >> 22) & 1;
14145      if (rD == 15) {
14146         /* forget it */
14147      } else {
14148         if (isT) {
14149            putIRegA(rD,
14150                     binop(Iop_Or32,
14151                           binop(Iop_And32, getIRegA(rD), mkU32(0xFFFF)),
14152                           mkU32(imm16 << 16)),
14153                     condT, Ijk_Boring);
14154            DIP("movt%s r%u, #0x%04x\n", nCC(INSN_COND), rD, imm16);
14155            goto decode_success;
14156         } else {
14157            putIRegA(rD, mkU32(imm16), condT, Ijk_Boring);
14158            DIP("movw%s r%u, #0x%04x\n", nCC(INSN_COND), rD, imm16);
14159            goto decode_success;
14160         }
14161      }
14162      /* fall through */
14163   }
14164
14165   /* ----------- uxtb, sxtb, uxth, sxth, uxtb16, sxtb16 ----------- */
14166   /* FIXME: this is an exact duplicate of the Thumb version.  They
14167      should be commoned up. */
14168   if (BITS8(0,1,1,0,1, 0,0,0) == (INSN(27,20) & BITS8(1,1,1,1,1,0,0,0))
14169       && BITS4(1,1,1,1) == INSN(19,16)
14170       && BITS4(0,1,1,1) == INSN(7,4)
14171       && BITS4(0,0, 0,0) == (INSN(11,8) & BITS4(0,0,1,1))) {
14172      UInt subopc = INSN(27,20) & BITS8(0,0,0,0,0, 1,1,1);
14173      if (subopc != BITS4(0,0,0,1) && subopc != BITS4(0,1,0,1)) {
14174         Int    rot  = (INSN(11,8) >> 2) & 3;
14175         UInt   rM   = INSN(3,0);
14176         UInt   rD   = INSN(15,12);
14177         IRTemp srcT = newTemp(Ity_I32);
14178         IRTemp rotT = newTemp(Ity_I32);
14179         IRTemp dstT = newTemp(Ity_I32);
14180         HChar* nm   = "???";
14181         assign(srcT, getIRegA(rM));
14182         assign(rotT, genROR32(srcT, 8 * rot)); /* 0, 8, 16 or 24 only */
14183         switch (subopc) {
14184            case BITS4(0,1,1,0): // UXTB
14185               assign(dstT, unop(Iop_8Uto32, unop(Iop_32to8, mkexpr(rotT))));
14186               nm = "uxtb";
14187               break;
14188            case BITS4(0,0,1,0): // SXTB
14189               assign(dstT, unop(Iop_8Sto32, unop(Iop_32to8, mkexpr(rotT))));
14190               nm = "sxtb";
14191               break;
14192            case BITS4(0,1,1,1): // UXTH
14193               assign(dstT, unop(Iop_16Uto32, unop(Iop_32to16, mkexpr(rotT))));
14194               nm = "uxth";
14195               break;
14196            case BITS4(0,0,1,1): // SXTH
14197               assign(dstT, unop(Iop_16Sto32, unop(Iop_32to16, mkexpr(rotT))));
14198               nm = "sxth";
14199               break;
14200            case BITS4(0,1,0,0): // UXTB16
14201               assign(dstT, binop(Iop_And32, mkexpr(rotT), mkU32(0x00FF00FF)));
14202               nm = "uxtb16";
14203               break;
14204            case BITS4(0,0,0,0): { // SXTB16
14205               IRTemp lo32 = newTemp(Ity_I32);
14206               IRTemp hi32 = newTemp(Ity_I32);
14207               assign(lo32, binop(Iop_And32, mkexpr(rotT), mkU32(0xFF)));
14208               assign(hi32, binop(Iop_Shr32, mkexpr(rotT), mkU8(16)));
14209               assign(
14210                  dstT,
14211                  binop(Iop_Or32,
14212                        binop(Iop_And32,
14213                              unop(Iop_8Sto32,
14214                                   unop(Iop_32to8, mkexpr(lo32))),
14215                              mkU32(0xFFFF)),
14216                        binop(Iop_Shl32,
14217                              unop(Iop_8Sto32,
14218                                   unop(Iop_32to8, mkexpr(hi32))),
14219                              mkU8(16))
14220               ));
14221               nm = "sxtb16";
14222               break;
14223            }
14224            default:
14225               vassert(0); // guarded by "if" above
14226         }
14227         putIRegA(rD, mkexpr(dstT), condT, Ijk_Boring);
14228         DIP("%s%s r%u, r%u, ROR #%u\n", nm, nCC(INSN_COND), rD, rM, rot);
14229         goto decode_success;
14230      }
14231      /* fall through */
14232   }
14233
14234   /* ------------------- bfi, bfc ------------------- */
14235   if (BITS8(0,1,1,1,1,1,0, 0) == (INSN(27,20) & BITS8(1,1,1,1,1,1,1,0))
14236       && BITS4(0, 0,0,1) == (INSN(7,4) & BITS4(0,1,1,1))) {
14237      UInt rD  = INSN(15,12);
14238      UInt rN  = INSN(3,0);
14239      UInt msb = (insn >> 16) & 0x1F; /* 20:16 */
14240      UInt lsb = (insn >> 7) & 0x1F;  /* 11:7 */
14241      if (rD == 15 || msb < lsb) {
14242         /* undecodable; fall through */
14243      } else {
14244         IRTemp src    = newTemp(Ity_I32);
14245         IRTemp olddst = newTemp(Ity_I32);
14246         IRTemp newdst = newTemp(Ity_I32);
14247         UInt   mask = 1 << (msb - lsb);
14248         mask = (mask - 1) + mask;
14249         vassert(mask != 0); // guaranteed by "msb < lsb" check above
14250         mask <<= lsb;
14251
14252         assign(src, rN == 15 ? mkU32(0) : getIRegA(rN));
14253         assign(olddst, getIRegA(rD));
14254         assign(newdst,
14255                binop(Iop_Or32,
14256                   binop(Iop_And32,
14257                         binop(Iop_Shl32, mkexpr(src), mkU8(lsb)),
14258                         mkU32(mask)),
14259                   binop(Iop_And32,
14260                         mkexpr(olddst),
14261                         mkU32(~mask)))
14262               );
14263
14264         putIRegA(rD, mkexpr(newdst), condT, Ijk_Boring);
14265
14266         if (rN == 15) {
14267            DIP("bfc%s r%u, #%u, #%u\n",
14268                nCC(INSN_COND), rD, lsb, msb-lsb+1);
14269         } else {
14270            DIP("bfi%s r%u, r%u, #%u, #%u\n",
14271                nCC(INSN_COND), rD, rN, lsb, msb-lsb+1);
14272         }
14273         goto decode_success;
14274      }
14275      /* fall through */
14276   }
14277
14278   /* ------------------- {u,s}bfx ------------------- */
14279   if (BITS8(0,1,1,1,1,0,1,0) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,0))
14280       && BITS4(0,1,0,1) == (INSN(7,4) & BITS4(0,1,1,1))) {
14281      UInt rD  = INSN(15,12);
14282      UInt rN  = INSN(3,0);
14283      UInt wm1 = (insn >> 16) & 0x1F; /* 20:16 */
14284      UInt lsb = (insn >> 7) & 0x1F;  /* 11:7 */
14285      UInt msb = lsb + wm1;
14286      UInt isU = (insn >> 22) & 1;    /* 22:22 */
14287      if (rD == 15 || rN == 15 || msb >= 32) {
14288         /* undecodable; fall through */
14289      } else {
14290         IRTemp src  = newTemp(Ity_I32);
14291         IRTemp tmp  = newTemp(Ity_I32);
14292         IRTemp res  = newTemp(Ity_I32);
14293         UInt   mask = ((1 << wm1) - 1) + (1 << wm1);
14294         vassert(msb >= 0 && msb <= 31);
14295         vassert(mask != 0); // guaranteed by msb being in 0 .. 31 inclusive
14296
14297         assign(src, getIRegA(rN));
14298         assign(tmp, binop(Iop_And32,
14299                           binop(Iop_Shr32, mkexpr(src), mkU8(lsb)),
14300                           mkU32(mask)));
14301         assign(res, binop(isU ? Iop_Shr32 : Iop_Sar32,
14302                           binop(Iop_Shl32, mkexpr(tmp), mkU8(31-wm1)),
14303                           mkU8(31-wm1)));
14304
14305         putIRegA(rD, mkexpr(res), condT, Ijk_Boring);
14306
14307         DIP("%s%s r%u, r%u, #%u, #%u\n",
14308             isU ? "ubfx" : "sbfx",
14309             nCC(INSN_COND), rD, rN, lsb, wm1 + 1);
14310         goto decode_success;
14311      }
14312      /* fall through */
14313   }
14314
14315   /* --------------------- Load/store doubleword ------------- */
14316   // LDRD STRD
14317   /*                 31   27   23   19 15 11   7    3     # highest bit
14318                        28   24   20 16 12    8    4    0
14319      A5-36   1 | 16  cond 0001 U100 Rn Rd im4h 11S1 im4l
14320      A5-38   1 | 32  cond 0001 U000 Rn Rd 0000 11S1 Rm
14321      A5-40   2 | 16  cond 0001 U110 Rn Rd im4h 11S1 im4l
14322      A5-42   2 | 32  cond 0001 U010 Rn Rd 0000 11S1 Rm
14323      A5-44   3 | 16  cond 0000 U100 Rn Rd im4h 11S1 im4l
14324      A5-46   3 | 32  cond 0000 U000 Rn Rd 0000 11S1 Rm
14325   */
14326   /* case coding:
14327             1   at-ea               (access at ea)
14328             2   at-ea-then-upd      (access at ea, then Rn = ea)
14329             3   at-Rn-then-upd      (access at Rn, then Rn = ea)
14330      ea coding
14331             16  Rn +/- imm8
14332             32  Rn +/- Rm
14333   */
14334   /* Quickly skip over all of this for hopefully most instructions */
14335   if ((INSN(27,24) & BITS4(1,1,1,0)) != BITS4(0,0,0,0))
14336      goto after_load_store_doubleword;
14337
14338   /* Check the "11S1" thing. */
14339   if ((INSN(7,4) & BITS4(1,1,0,1)) != BITS4(1,1,0,1))
14340      goto after_load_store_doubleword;
14341
14342   summary = 0;
14343
14344   /**/ if (INSN(27,24) == BITS4(0,0,0,1) && INSN(22,20) == BITS3(1,0,0)) {
14345      summary = 1 | 16;
14346   }
14347   else if (INSN(27,24) == BITS4(0,0,0,1) && INSN(22,20) == BITS3(0,0,0)) {
14348      summary = 1 | 32;
14349   }
14350   else if (INSN(27,24) == BITS4(0,0,0,1) && INSN(22,20) == BITS3(1,1,0)) {
14351      summary = 2 | 16;
14352   }
14353   else if (INSN(27,24) == BITS4(0,0,0,1) && INSN(22,20) == BITS3(0,1,0)) {
14354      summary = 2 | 32;
14355   }
14356   else if (INSN(27,24) == BITS4(0,0,0,0) && INSN(22,20) == BITS3(1,0,0)) {
14357      summary = 3 | 16;
14358   }
14359   else if (INSN(27,24) == BITS4(0,0,0,0) && INSN(22,20) == BITS3(0,0,0)) {
14360      summary = 3 | 32;
14361   }
14362   else goto after_load_store_doubleword;
14363
14364   { UInt rN   = (insn >> 16) & 0xF; /* 19:16 */
14365     UInt rD   = (insn >> 12) & 0xF; /* 15:12 */
14366     UInt rM   = (insn >> 0)  & 0xF; /*  3:0  */
14367     UInt bU   = (insn >> 23) & 1;   /* 23 U=1 offset+, U=0 offset- */
14368     UInt bS   = (insn >> 5) & 1;    /* S=1 store, S=0 load */
14369     UInt imm8 = ((insn >> 4) & 0xF0) | (insn & 0xF); /* 11:8, 3:0 */
14370
14371     /* Require rD to be an even numbered register */
14372     if ((rD & 1) != 0)
14373        goto after_load_store_doubleword;
14374
14375     /* Require 11:8 == 0 for Rn +/- Rm cases */
14376     if ((summary & 32) != 0 && (imm8 & 0xF0) != 0)
14377        goto after_load_store_doubleword;
14378
14379     /* Skip some invalid cases, which would lead to two competing
14380        updates to the same register, or which are otherwise
14381        disallowed by the spec. */
14382     switch (summary) {
14383        case 1 | 16:
14384           break;
14385        case 1 | 32:
14386           if (rM == 15) goto after_load_store_doubleword;
14387           break;
14388        case 2 | 16: case 3 | 16:
14389           if (rN == 15) goto after_load_store_doubleword;
14390           if (bS == 0 && (rN == rD || rN == rD+1))
14391              goto after_load_store_doubleword;
14392           break;
14393        case 2 | 32: case 3 | 32:
14394           if (rM == 15) goto after_load_store_doubleword;
14395           if (rN == 15) goto after_load_store_doubleword;
14396           if (rN == rM) goto after_load_store_doubleword;
14397           if (bS == 0 && (rN == rD || rN == rD+1))
14398              goto after_load_store_doubleword;
14399           break;
14400        default:
14401           vassert(0);
14402     }
14403
14404     /* Now, we can't do a conditional load or store, since that very
14405        likely will generate an exception.  So we have to take a side
14406        exit at this point if the condition is false. */
14407     if (condT != IRTemp_INVALID) {
14408        mk_skip_over_A32_if_cond_is_false( condT );
14409        condT = IRTemp_INVALID;
14410     }
14411     /* Ok, now we're unconditional.  Do the load or store. */
14412
14413     /* compute the effective address.  Bind it to a tmp since we
14414        may need to use it twice. */
14415     IRExpr* eaE = NULL;
14416     switch (summary & 0xF0) {
14417        case 16:
14418           eaE = mk_EA_reg_plusminus_imm8( rN, bU, imm8, dis_buf );
14419           break;
14420        case 32:
14421           eaE = mk_EA_reg_plusminus_reg( rN, bU, rM, dis_buf );
14422           break;
14423     }
14424     vassert(eaE);
14425     IRTemp eaT = newTemp(Ity_I32);
14426     assign(eaT, eaE);
14427
14428     /* get the old Rn value */
14429     IRTemp rnT = newTemp(Ity_I32);
14430     assign(rnT, getIRegA(rN));
14431
14432     /* decide on the transfer address */
14433     IRTemp taT = IRTemp_INVALID;
14434     switch (summary & 0x0F) {
14435        case 1: case 2: taT = eaT; break;
14436        case 3:         taT = rnT; break;
14437     }
14438     vassert(taT != IRTemp_INVALID);
14439
14440     /* XXX deal with alignment constraints */
14441     /* XXX: but the A8 doesn't seem to trap for misaligned loads, so,
14442        ignore alignment issues for the time being. */
14443
14444     /* doubleword store  S 1
14445        doubleword load   S 0
14446     */
14447     HChar* name = NULL;
14448     /* generate the transfers */
14449     if (bS == 1) { // doubleword store
14450        storeLE( binop(Iop_Add32, mkexpr(taT), mkU32(0)), getIRegA(rD+0) );
14451        storeLE( binop(Iop_Add32, mkexpr(taT), mkU32(4)), getIRegA(rD+1) );
14452        name = "strd";
14453     } else { // doubleword load
14454        putIRegA( rD+0,
14455                  loadLE(Ity_I32, binop(Iop_Add32, mkexpr(taT), mkU32(0))),
14456                  IRTemp_INVALID, Ijk_Boring );
14457        putIRegA( rD+1,
14458                  loadLE(Ity_I32, binop(Iop_Add32, mkexpr(taT), mkU32(4))),
14459                  IRTemp_INVALID, Ijk_Boring );
14460        name = "ldrd";
14461     }
14462
14463     /* Update Rn if necessary. */
14464     switch (summary & 0x0F) {
14465        case 2: case 3:
14466           // should be assured by logic above:
14467           if (bS == 0) {
14468              vassert(rD+0 != rN); /* since we just wrote rD+0 */
14469              vassert(rD+1 != rN); /* since we just wrote rD+1 */
14470           }
14471           putIRegA( rN, mkexpr(eaT), IRTemp_INVALID, Ijk_Boring );
14472           break;
14473     }
14474
14475     switch (summary & 0x0F) {
14476        case 1:  DIP("%s%s r%u, %s\n", name, nCC(INSN_COND), rD, dis_buf);
14477                 break;
14478        case 2:  DIP("%s%s r%u, %s! (at-EA-then-Rn=EA)\n",
14479                     name, nCC(INSN_COND), rD, dis_buf);
14480                 break;
14481        case 3:  DIP("%s%s r%u, %s! (at-Rn-then-Rn=EA)\n",
14482                     name, nCC(INSN_COND), rD, dis_buf);
14483                 break;
14484        default: vassert(0);
14485     }
14486
14487     goto decode_success;
14488   }
14489
14490  after_load_store_doubleword:
14491
14492   /* ------------------- {s,u}xtab ------------- */
14493   if (BITS8(0,1,1,0,1,0,1,0) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,1))
14494       && BITS4(0,0,0,0) == (INSN(11,8) & BITS4(0,0,1,1))
14495       && BITS4(0,1,1,1) == INSN(7,4)) {
14496      UInt rN  = INSN(19,16);
14497      UInt rD  = INSN(15,12);
14498      UInt rM  = INSN(3,0);
14499      UInt rot = (insn >> 10) & 3;
14500      UInt isU = INSN(22,22);
14501      if (rN == 15/*it's {S,U}XTB*/ || rD == 15 || rM == 15) {
14502         /* undecodable; fall through */
14503      } else {
14504         IRTemp srcL = newTemp(Ity_I32);
14505         IRTemp srcR = newTemp(Ity_I32);
14506         IRTemp res  = newTemp(Ity_I32);
14507         assign(srcR, getIRegA(rM));
14508         assign(srcL, getIRegA(rN));
14509         assign(res,  binop(Iop_Add32,
14510                            mkexpr(srcL),
14511                            unop(isU ? Iop_8Uto32 : Iop_8Sto32,
14512                                 unop(Iop_32to8,
14513                                      genROR32(srcR, 8 * rot)))));
14514         putIRegA(rD, mkexpr(res), condT, Ijk_Boring);
14515         DIP("%cxtab%s r%u, r%u, r%u, ror #%u\n",
14516             isU ? 'u' : 's', nCC(INSN_COND), rD, rN, rM, rot);
14517         goto decode_success;
14518      }
14519      /* fall through */
14520   }
14521
14522   /* ------------------- {s,u}xtah ------------- */
14523   if (BITS8(0,1,1,0,1,0,1,1) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,1))
14524       && BITS4(0,0,0,0) == (INSN(11,8) & BITS4(0,0,1,1))
14525       && BITS4(0,1,1,1) == INSN(7,4)) {
14526      UInt rN  = INSN(19,16);
14527      UInt rD  = INSN(15,12);
14528      UInt rM  = INSN(3,0);
14529      UInt rot = (insn >> 10) & 3;
14530      UInt isU = INSN(22,22);
14531      if (rN == 15/*it's {S,U}XTH*/ || rD == 15 || rM == 15) {
14532         /* undecodable; fall through */
14533      } else {
14534         IRTemp srcL = newTemp(Ity_I32);
14535         IRTemp srcR = newTemp(Ity_I32);
14536         IRTemp res  = newTemp(Ity_I32);
14537         assign(srcR, getIRegA(rM));
14538         assign(srcL, getIRegA(rN));
14539         assign(res,  binop(Iop_Add32,
14540                            mkexpr(srcL),
14541                            unop(isU ? Iop_16Uto32 : Iop_16Sto32,
14542                                 unop(Iop_32to16,
14543                                      genROR32(srcR, 8 * rot)))));
14544         putIRegA(rD, mkexpr(res), condT, Ijk_Boring);
14545
14546         DIP("%cxtah%s r%u, r%u, r%u, ror #%u\n",
14547             isU ? 'u' : 's', nCC(INSN_COND), rD, rN, rM, rot);
14548         goto decode_success;
14549      }
14550      /* fall through */
14551   }
14552
14553   /* ------------------- rev16, rev ------------------ */
14554   if (INSN(27,16) == 0x6BF
14555       && (INSN(11,4) == 0xFB/*rev16*/ || INSN(11,4) == 0xF3/*rev*/)) {
14556      Bool isREV = INSN(11,4) == 0xF3;
14557      UInt rM    = INSN(3,0);
14558      UInt rD    = INSN(15,12);
14559      if (rM != 15 && rD != 15) {
14560         IRTemp rMt = newTemp(Ity_I32);
14561         assign(rMt, getIRegA(rM));
14562         IRTemp res = isREV ? gen_REV(rMt) : gen_REV16(rMt);
14563         putIRegA(rD, mkexpr(res), condT, Ijk_Boring);
14564         DIP("rev%s%s r%u, r%u\n", isREV ? "" : "16",
14565             nCC(INSN_COND), rD, rM);
14566         goto decode_success;
14567      }
14568   }
14569
14570   /* ------------------- rbit ------------------ */
14571   if (INSN(27,16) == 0x6FF && INSN(11,4) == 0xF3) {
14572      UInt rD = INSN(15,12);
14573      UInt rM = INSN(3,0);
14574      if (rD != 15 && rM != 15) {
14575         IRTemp arg = newTemp(Ity_I32);
14576         assign(arg, getIRegA(rM));
14577         IRTemp res = gen_BITREV(arg);
14578         putIRegA(rD, mkexpr(res), condT, Ijk_Boring);
14579         DIP("rbit r%u, r%u\n", rD, rM);
14580         goto decode_success;
14581      }
14582   }
14583
14584   /* ------------------- smmul ------------------ */
14585   if (INSN(27,20) == BITS8(0,1,1,1,0,1,0,1)
14586       && INSN(15,12) == BITS4(1,1,1,1)
14587       && (INSN(7,4) & BITS4(1,1,0,1)) == BITS4(0,0,0,1)) {
14588      UInt bitR = INSN(5,5);
14589      UInt rD = INSN(19,16);
14590      UInt rM = INSN(11,8);
14591      UInt rN = INSN(3,0);
14592      if (rD != 15 && rM != 15 && rN != 15) {
14593         IRExpr* res
14594         = unop(Iop_64HIto32,
14595                binop(Iop_Add64,
14596                      binop(Iop_MullS32, getIRegA(rN), getIRegA(rM)),
14597                      mkU64(bitR ? 0x80000000ULL : 0ULL)));
14598         putIRegA(rD, res, condT, Ijk_Boring);
14599         DIP("smmul%s%s r%u, r%u, r%u\n",
14600             nCC(INSN_COND), bitR ? "r" : "", rD, rN, rM);
14601         goto decode_success;
14602      }
14603   }
14604
14605   /* ------------------- smmla ------------------ */
14606   if (INSN(27,20) == BITS8(0,1,1,1,0,1,0,1)
14607       && INSN(15,12) != BITS4(1,1,1,1)
14608       && (INSN(7,4) & BITS4(1,1,0,1)) == BITS4(0,0,0,1)) {
14609      UInt bitR = INSN(5,5);
14610      UInt rD = INSN(19,16);
14611      UInt rA = INSN(15,12);
14612      UInt rM = INSN(11,8);
14613      UInt rN = INSN(3,0);
14614      if (rD != 15 && rM != 15 && rN != 15) {
14615         IRExpr* res
14616         = unop(Iop_64HIto32,
14617                binop(Iop_Add64,
14618                      binop(Iop_Add64,
14619                            binop(Iop_32HLto64, getIRegA(rA), mkU32(0)),
14620                            binop(Iop_MullS32, getIRegA(rN), getIRegA(rM))),
14621                      mkU64(bitR ? 0x80000000ULL : 0ULL)));
14622         putIRegA(rD, res, condT, Ijk_Boring);
14623         DIP("smmla%s%s r%u, r%u, r%u, r%u\n",
14624             nCC(INSN_COND), bitR ? "r" : "", rD, rN, rM, rA);
14625         goto decode_success;
14626      }
14627   }
14628
14629   /* ------------------- NOP ------------------ */
14630   if (0x0320F000 == (insn & 0x0FFFFFFF)) {
14631      DIP("nop%s\n", nCC(INSN_COND));
14632      goto decode_success;
14633   }
14634
14635   /* ----------------------------------------------------------- */
14636   /* -- ARMv7 instructions                                    -- */
14637   /* ----------------------------------------------------------- */
14638
14639   /* -------------- read CP15 TPIDRURO register ------------- */
14640   /* mrc     p15, 0, r0, c13, c0, 3  up to
14641      mrc     p15, 0, r14, c13, c0, 3
14642   */
14643   /* I don't know whether this is really v7-only.  But anyway, we
14644      have to support it since arm-linux uses TPIDRURO as a thread
14645      state register. */
14646   if (0x0E1D0F70 == (insn & 0x0FFF0FFF)) {
14647      UInt rD = INSN(15,12);
14648      if (rD <= 14) {
14649         /* skip r15, that's too stupid to handle */
14650         putIRegA(rD, IRExpr_Get(OFFB_TPIDRURO, Ity_I32),
14651                      condT, Ijk_Boring);
14652         DIP("mrc%s p15,0, r%u, c13, c0, 3\n", nCC(INSN_COND), rD);
14653         goto decode_success;
14654      }
14655      /* fall through */
14656   }
14657
14658   /* Handle various kinds of barriers.  This is rather indiscriminate
14659      in the sense that they are all turned into an IR Fence, which
14660      means we don't know which they are, so the back end has to
14661      re-emit them all when it comes acrosss an IR Fence.
14662   */
14663   /* v6 */ /* mcr 15, 0, rT, c7, c10, 5 */
14664   if (0xEE070FBA == (insn & 0xFFFF0FFF)) {
14665      UInt rT = INSN(15,12);
14666      if (rT <= 14) {
14667         /* mcr 15, 0, rT, c7, c10, 5 (v6) equiv to DMB (v7).  Data
14668            Memory Barrier -- ensures ordering of memory accesses. */
14669         stmt( IRStmt_MBE(Imbe_Fence) );
14670         DIP("mcr 15, 0, r%u, c7, c10, 5 (data memory barrier)\n", rT);
14671         goto decode_success;
14672      }
14673      /* fall through */
14674   }
14675   /* other flavours of barrier */
14676   switch (insn) {
14677      case 0xEE070F9A: /* v6 */
14678         /* mcr 15, 0, r0, c7, c10, 4 (v6) equiv to DSB (v7).  Data
14679            Synch Barrier -- ensures completion of memory accesses. */
14680         stmt( IRStmt_MBE(Imbe_Fence) );
14681         DIP("mcr 15, 0, r0, c7, c10, 4 (data synch barrier)\n");
14682         goto decode_success;
14683      case 0xEE070F95: /* v6 */
14684         /* mcr 15, 0, r0, c7, c5, 4 (v6) equiv to ISB (v7).
14685            Instruction Synchronisation Barrier (or Flush Prefetch
14686            Buffer) -- a pipe flush, I think.  I suspect we could
14687            ignore those, but to be on the safe side emit a fence
14688            anyway. */
14689         stmt( IRStmt_MBE(Imbe_Fence) );
14690         DIP("mcr 15, 0, r0, c7, c5, 4 (insn synch barrier)\n");
14691         goto decode_success;
14692      default:
14693         break;
14694   }
14695
14696   /* ----------------------------------------------------------- */
14697   /* -- VFP (CP 10, CP 11) instructions (in ARM mode)         -- */
14698   /* ----------------------------------------------------------- */
14699
14700   if (INSN_COND != ARMCondNV) {
14701      Bool ok_vfp = decode_CP10_CP11_instruction (
14702                       &dres, INSN(27,0), condT, INSN_COND,
14703                       False/*!isT*/
14704                    );
14705      if (ok_vfp)
14706         goto decode_success;
14707   }
14708
14709   /* ----------------------------------------------------------- */
14710   /* -- NEON instructions (in ARM mode)                       -- */
14711   /* ----------------------------------------------------------- */
14712
14713   /* These are all in NV space, and so are taken care of (far) above,
14714      by a call from this function to decode_NV_instruction(). */
14715
14716   /* ----------------------------------------------------------- */
14717   /* -- v6 media instructions (in ARM mode)                   -- */
14718   /* ----------------------------------------------------------- */
14719
14720   { Bool ok_v6m = decode_V6MEDIA_instruction(
14721                       &dres, INSN(27,0), condT, INSN_COND,
14722                       False/*!isT*/
14723                   );
14724     if (ok_v6m)
14725        goto decode_success;
14726   }
14727
14728   /* ----------------------------------------------------------- */
14729   /* -- Undecodable                                           -- */
14730   /* ----------------------------------------------------------- */
14731
14732   goto decode_failure;
14733   /*NOTREACHED*/
14734
14735  decode_failure:
14736   /* All decode failures end up here. */
14737   vex_printf("disInstr(arm): unhandled instruction: "
14738              "0x%x\n", insn);
14739   vex_printf("                 cond=%d(0x%x) 27:20=%u(0x%02x) "
14740                                "4:4=%d "
14741                                "3:0=%u(0x%x)\n",
14742              (Int)INSN_COND, (UInt)INSN_COND,
14743              (Int)INSN(27,20), (UInt)INSN(27,20),
14744              (Int)INSN(4,4),
14745              (Int)INSN(3,0), (UInt)INSN(3,0) );
14746
14747   /* Tell the dispatcher that this insn cannot be decoded, and so has
14748      not been executed, and (is currently) the next to be executed.
14749      R15 should be up-to-date since it made so at the start of each
14750      insn, but nevertheless be paranoid and update it again right
14751      now. */
14752   vassert(0 == (guest_R15_curr_instr_notENC & 3));
14753   llPutIReg( 15, mkU32(guest_R15_curr_instr_notENC) );
14754   dres.whatNext    = Dis_StopHere;
14755   dres.jk_StopHere = Ijk_NoDecode;
14756   dres.len         = 0;
14757   return dres;
14758
14759  decode_success:
14760   /* All decode successes end up here. */
14761   DIP("\n");
14762
14763   vassert(dres.len == 4 || dres.len == 20);
14764
14765   /* Now then.  Do we have an implicit jump to r15 to deal with? */
14766   if (r15written) {
14767      /* If we get jump to deal with, we assume that there's been no
14768         other competing branch stuff previously generated for this
14769         insn.  That's reasonable, in the sense that the ARM insn set
14770         appears to declare as "Unpredictable" any instruction which
14771         generates more than one possible new value for r15.  Hence
14772         just assert.  The decoders themselves should check against
14773         all such instructions which are thusly Unpredictable, and
14774         decline to decode them.  Hence we should never get here if we
14775         have competing new values for r15, and hence it is safe to
14776         assert here. */
14777      vassert(dres.whatNext == Dis_Continue);
14778      vassert(irsb->next == NULL);
14779      vassert(irsb->jumpkind == Ijk_Boring);
14780      /* If r15 is unconditionally written, terminate the block by
14781         jumping to it.  If it's conditionally written, still
14782         terminate the block (a shame, but we can't do side exits to
14783         arbitrary destinations), but first jump to the next
14784         instruction if the condition doesn't hold. */
14785      /* We can't use getIReg(15) to get the destination, since that
14786         will produce r15+8, which isn't what we want.  Must use
14787         llGetIReg(15) instead. */
14788      if (r15guard == IRTemp_INVALID) {
14789         /* unconditional */
14790      } else {
14791         /* conditional */
14792         stmt( IRStmt_Exit(
14793                  unop(Iop_32to1,
14794                       binop(Iop_Xor32,
14795                             mkexpr(r15guard), mkU32(1))),
14796                  r15kind,
14797                  IRConst_U32(guest_R15_curr_instr_notENC + 4),
14798                  OFFB_R15T
14799         ));
14800      }
14801      /* This seems crazy, but we're required to finish the insn with
14802         a write to the guest PC.  As usual we rely on ir_opt to tidy
14803         up later. */
14804      llPutIReg(15, llGetIReg(15));
14805      dres.whatNext    = Dis_StopHere;
14806      dres.jk_StopHere = r15kind;
14807   } else {
14808      /* Set up the end-state in the normal way. */
14809      switch (dres.whatNext) {
14810         case Dis_Continue:
14811            llPutIReg(15, mkU32(dres.len + guest_R15_curr_instr_notENC));
14812            break;
14813         case Dis_ResteerU:
14814         case Dis_ResteerC:
14815            llPutIReg(15, mkU32(dres.continueAt));
14816            break;
14817         case Dis_StopHere:
14818            break;
14819         default:
14820            vassert(0);
14821      }
14822   }
14823
14824   return dres;
14825
14826#  undef INSN_COND
14827#  undef INSN
14828}
14829
14830
14831/*------------------------------------------------------------*/
14832/*--- Disassemble a single Thumb2 instruction              ---*/
14833/*------------------------------------------------------------*/
14834
14835static const UChar it_length_table[256]; /* fwds */
14836
14837/* NB: in Thumb mode we do fetches of regs with getIRegT, which
14838   automagically adds 4 to fetches of r15.  However, writes to regs
14839   are done with putIRegT, which disallows writes to r15.  Hence any
14840   r15 writes and associated jumps have to be done "by hand". */
14841
14842/* Disassemble a single Thumb instruction into IR.  The instruction is
14843   located in host memory at guest_instr, and has (decoded) guest IP
14844   of guest_R15_curr_instr_notENC, which will have been set before the
14845   call here. */
14846
14847static
14848DisResult disInstr_THUMB_WRK (
14849             Bool         (*resteerOkFn) ( /*opaque*/void*, Addr64 ),
14850             Bool         resteerCisOk,
14851             void*        callback_opaque,
14852             UChar*       guest_instr,
14853             VexArchInfo* archinfo,
14854             VexAbiInfo*  abiinfo
14855          )
14856{
14857   /* A macro to fish bits out of insn0.  There's also INSN1, to fish
14858      bits out of insn1, but that's defined only after the end of the
14859      16-bit insn decoder, so as to stop it mistakenly being used
14860      therein. */
14861#  define INSN0(_bMax,_bMin)  SLICE_UInt(((UInt)insn0), (_bMax), (_bMin))
14862
14863   DisResult dres;
14864   UShort    insn0; /*  first 16 bits of the insn */
14865   UShort    insn1; /* second 16 bits of the insn */
14866   //Bool      allow_VFP = False;
14867   //UInt      hwcaps = archinfo->hwcaps;
14868   HChar     dis_buf[128];  // big enough to hold LDMIA etc text
14869
14870   /* Summary result of the ITxxx backwards analysis: False == safe
14871      but suboptimal. */
14872   Bool guaranteedUnconditional = False;
14873
14874   /* What insn variants are we supporting today? */
14875   //allow_VFP  = (0 != (hwcaps & VEX_HWCAPS_ARM_VFP));
14876   // etc etc
14877
14878   /* Set result defaults. */
14879   dres.whatNext    = Dis_Continue;
14880   dres.len         = 2;
14881   dres.continueAt  = 0;
14882   dres.jk_StopHere = Ijk_INVALID;
14883
14884   /* Set default actions for post-insn handling of writes to r15, if
14885      required. */
14886   r15written = False;
14887   r15guard   = IRTemp_INVALID; /* unconditional */
14888   r15kind    = Ijk_Boring;
14889
14890   /* Insns could be 2 or 4 bytes long.  Just get the first 16 bits at
14891      this point.  If we need the second 16, get them later.  We can't
14892      get them both out immediately because it risks a fault (very
14893      unlikely, but ..) if the second 16 bits aren't actually
14894      necessary. */
14895   insn0 = getUShortLittleEndianly( guest_instr );
14896   insn1 = 0; /* We'll get it later, once we know we need it. */
14897
14898   /* Similarly, will set this later. */
14899   IRTemp old_itstate = IRTemp_INVALID;
14900
14901   if (0) vex_printf("insn: 0x%x\n", insn0);
14902
14903   DIP("\t(thumb) 0x%x:  ", (UInt)guest_R15_curr_instr_notENC);
14904
14905   vassert(0 == (guest_R15_curr_instr_notENC & 1));
14906
14907   /* ----------------------------------------------------------- */
14908   /* Spot "Special" instructions (see comment at top of file). */
14909   {
14910      UChar* code = (UChar*)guest_instr;
14911      /* Spot the 16-byte preamble:
14912
14913         ea4f 0cfc  mov.w   ip, ip, ror #3
14914         ea4f 3c7c  mov.w   ip, ip, ror #13
14915         ea4f 7c7c  mov.w   ip, ip, ror #29
14916         ea4f 4cfc  mov.w   ip, ip, ror #19
14917      */
14918      UInt word1 = 0x0CFCEA4F;
14919      UInt word2 = 0x3C7CEA4F;
14920      UInt word3 = 0x7C7CEA4F;
14921      UInt word4 = 0x4CFCEA4F;
14922      if (getUIntLittleEndianly(code+ 0) == word1 &&
14923          getUIntLittleEndianly(code+ 4) == word2 &&
14924          getUIntLittleEndianly(code+ 8) == word3 &&
14925          getUIntLittleEndianly(code+12) == word4) {
14926         /* Got a "Special" instruction preamble.  Which one is it? */
14927         // 0x 0A 0A EA 4A
14928         if (getUIntLittleEndianly(code+16) == 0x0A0AEA4A
14929                                               /* orr.w r10,r10,r10 */) {
14930            /* R3 = client_request ( R4 ) */
14931            DIP("r3 = client_request ( %%r4 )\n");
14932            llPutIReg(15, mkU32( (guest_R15_curr_instr_notENC + 20) | 1 ));
14933            dres.jk_StopHere = Ijk_ClientReq;
14934            dres.whatNext    = Dis_StopHere;
14935            goto decode_success;
14936         }
14937         else
14938         // 0x 0B 0B EA 4B
14939         if (getUIntLittleEndianly(code+16) == 0x0B0BEA4B
14940                                               /* orr r11,r11,r11 */) {
14941            /* R3 = guest_NRADDR */
14942            DIP("r3 = guest_NRADDR\n");
14943            dres.len = 20;
14944            llPutIReg(3, IRExpr_Get( OFFB_NRADDR, Ity_I32 ));
14945            goto decode_success;
14946         }
14947         else
14948         // 0x 0C 0C EA 4C
14949         if (getUIntLittleEndianly(code+16) == 0x0C0CEA4C
14950                                               /* orr r12,r12,r12 */) {
14951            /*  branch-and-link-to-noredir R4 */
14952            DIP("branch-and-link-to-noredir r4\n");
14953            llPutIReg(14, mkU32( (guest_R15_curr_instr_notENC + 20) | 1 ));
14954            llPutIReg(15, getIRegT(4));
14955            dres.jk_StopHere = Ijk_NoRedir;
14956            dres.whatNext    = Dis_StopHere;
14957            goto decode_success;
14958         }
14959         /* We don't know what it is.  Set insn0 so decode_failure
14960            can print the insn following the Special-insn preamble. */
14961         insn0 = getUShortLittleEndianly(code+16);
14962         goto decode_failure;
14963         /*NOTREACHED*/
14964      }
14965
14966   }
14967
14968   /* ----------------------------------------------------------- */
14969
14970   /* Main Thumb instruction decoder starts here.  It's a series of
14971      switches which examine ever longer bit sequences at the MSB of
14972      the instruction word, first for 16-bit insns, then for 32-bit
14973      insns. */
14974
14975   /* --- BEGIN ITxxx optimisation analysis --- */
14976   /* This is a crucial optimisation for the ITState boilerplate that
14977      follows.  Examine the 9 halfwords preceding this instruction,
14978      and if we are absolutely sure that none of them constitute an
14979      'it' instruction, then we can be sure that this instruction is
14980      not under the control of any 'it' instruction, and so
14981      guest_ITSTATE must be zero.  So write zero into ITSTATE right
14982      now, so that iropt can fold out almost all of the resulting
14983      junk.
14984
14985      If we aren't sure, we can always safely skip this step.  So be a
14986      bit conservative about it: only poke around in the same page as
14987      this instruction, lest we get a fault from the previous page
14988      that would not otherwise have happened.  The saving grace is
14989      that such skipping is pretty rare -- it only happens,
14990      statistically, 18/4096ths of the time, so is judged unlikely to
14991      be a performance problems.
14992
14993      FIXME: do better.  Take into account the number of insns covered
14994      by any IT insns we find, to rule out cases where an IT clearly
14995      cannot cover this instruction.  This would improve behaviour for
14996      branch targets immediately following an IT-guarded group that is
14997      not of full length.  Eg, (and completely ignoring issues of 16-
14998      vs 32-bit insn length):
14999
15000             ite cond
15001             insn1
15002             insn2
15003      label: insn3
15004             insn4
15005
15006      The 'it' only conditionalises insn1 and insn2.  However, the
15007      current analysis is conservative and considers insn3 and insn4
15008      also possibly guarded.  Hence if 'label:' is the start of a hot
15009      loop we will get a big performance hit.
15010   */
15011   {
15012      /* Summary result of this analysis: False == safe but
15013         suboptimal. */
15014      vassert(guaranteedUnconditional == False);
15015
15016      UInt pc = guest_R15_curr_instr_notENC;
15017      vassert(0 == (pc & 1));
15018
15019      UInt pageoff = pc & 0xFFF;
15020      if (pageoff >= 18) {
15021         /* It's safe to poke about in the 9 halfwords preceding this
15022            insn.  So, have a look at them. */
15023         guaranteedUnconditional = True; /* assume no 'it' insn found,
15024                                            till we do */
15025         UShort* hwp = (UShort*)(HWord)pc;
15026         Int i;
15027         for (i = -1; i >= -9; i--) {
15028            /* We're in the same page.  (True, but commented out due
15029               to expense.) */
15030            /*
15031            vassert( ( ((UInt)(&hwp[i])) & 0xFFFFF000 )
15032                      == ( pc & 0xFFFFF000 ) );
15033            */
15034            /* All valid IT instructions must have the form 0xBFxy,
15035               where x can be anything, but y must be nonzero.  Find
15036               the number of insns covered by it (1 .. 4) and check to
15037               see if it can possibly reach up to the instruction in
15038               question.  Some (x,y) combinations mean UNPREDICTABLE,
15039               and the table is constructed to be conservative by
15040               returning 4 for those cases, so the analysis is safe
15041               even if the code uses unpredictable IT instructions (in
15042               which case its authors are nuts, but hey.)  */
15043            UShort hwp_i = hwp[i];
15044            if (UNLIKELY((hwp_i & 0xFF00) == 0xBF00 && (hwp_i & 0xF) != 0)) {
15045               /* might be an 'it' insn. */
15046               /* # guarded insns */
15047               Int n_guarded = (Int)it_length_table[hwp_i & 0xFF];
15048               vassert(n_guarded >= 1 && n_guarded <= 4);
15049               if (n_guarded * 2 /* # guarded HWs, worst case */
15050                   > (-(i+1)))   /* -(i+1): # remaining HWs after the IT */
15051                   /* -(i+0) also seems to work, even though I think
15052                      it's wrong.  I don't understand that. */
15053                  guaranteedUnconditional = False;
15054               break;
15055            }
15056         }
15057      }
15058   }
15059   /* --- END ITxxx optimisation analysis --- */
15060
15061   /* Generate the guarding condition for this insn, by examining
15062      ITSTATE.  Assign it to condT.  Also, generate new
15063      values for ITSTATE ready for stuffing back into the
15064      guest state, but don't actually do the Put yet, since it will
15065      need to stuffed back in only after the instruction gets to a
15066      point where it is sure to complete.  Mostly we let the code at
15067      decode_success handle this, but in cases where the insn contains
15068      a side exit, we have to update them before the exit. */
15069
15070   /* If the ITxxx optimisation analysis above could not prove that
15071      this instruction is guaranteed unconditional, we insert a
15072      lengthy IR preamble to compute the guarding condition at
15073      runtime.  If it can prove it (which obviously we hope is the
15074      normal case) then we insert a minimal preamble, which is
15075      equivalent to setting guest_ITSTATE to zero and then folding
15076      that through the full preamble (which completely disappears). */
15077
15078   IRTemp condT              = IRTemp_INVALID;
15079   IRTemp cond_AND_notInIT_T = IRTemp_INVALID;
15080
15081   IRTemp new_itstate        = IRTemp_INVALID;
15082   vassert(old_itstate == IRTemp_INVALID);
15083
15084   if (guaranteedUnconditional) {
15085      /* BEGIN "partial eval { ITSTATE = 0; STANDARD_PREAMBLE; }" */
15086
15087      // ITSTATE = 0 :: I32
15088      IRTemp z32 = newTemp(Ity_I32);
15089      assign(z32, mkU32(0));
15090      put_ITSTATE(z32);
15091
15092      // old_itstate = 0 :: I32
15093      //
15094      // old_itstate = get_ITSTATE();
15095      old_itstate = z32; /* 0 :: I32 */
15096
15097      // new_itstate = old_itstate >> 8
15098      //             = 0 >> 8
15099      //             = 0 :: I32
15100      //
15101      // new_itstate = newTemp(Ity_I32);
15102      // assign(new_itstate,
15103      //        binop(Iop_Shr32, mkexpr(old_itstate), mkU8(8)));
15104      new_itstate = z32;
15105
15106      // ITSTATE = 0 :: I32(again)
15107      //
15108      // put_ITSTATE(new_itstate);
15109
15110      // condT1 = calc_cond_dyn( xor(and(old_istate,0xF0), 0xE0) )
15111      //        = calc_cond_dyn( xor(0,0xE0) )
15112      //        = calc_cond_dyn ( 0xE0 )
15113      //        = 1 :: I32
15114      // Not that this matters, since the computed value is not used:
15115      // see condT folding below
15116      //
15117      // IRTemp condT1 = newTemp(Ity_I32);
15118      // assign(condT1,
15119      //        mk_armg_calculate_condition_dyn(
15120      //           binop(Iop_Xor32,
15121      //                 binop(Iop_And32, mkexpr(old_itstate), mkU32(0xF0)),
15122      //                 mkU32(0xE0))
15123      //       )
15124      // );
15125
15126      // condT = 32to8(and32(old_itstate,0xF0)) == 0  ? 1  : condT1
15127      //       = 32to8(and32(0,0xF0)) == 0  ? 1  : condT1
15128      //       = 32to8(0) == 0  ? 1  : condT1
15129      //       = 0 == 0  ? 1  : condT1
15130      //       = 1
15131      //
15132      // condT = newTemp(Ity_I32);
15133      // assign(condT, IRExpr_Mux0X(
15134      //                  unop(Iop_32to8, binop(Iop_And32,
15135      //                                        mkexpr(old_itstate),
15136      //                                        mkU32(0xF0))),
15137      //                  mkU32(1),
15138      //                  mkexpr(condT1)
15139      //       ));
15140      condT = newTemp(Ity_I32);
15141      assign(condT, mkU32(1));
15142
15143      // notInITt = xor32(and32(old_itstate, 1), 1)
15144      //          = xor32(and32(0, 1), 1)
15145      //          = xor32(0, 1)
15146      //          = 1 :: I32
15147      //
15148      // IRTemp notInITt = newTemp(Ity_I32);
15149      // assign(notInITt,
15150      //        binop(Iop_Xor32,
15151      //              binop(Iop_And32, mkexpr(old_itstate), mkU32(1)),
15152      //              mkU32(1)));
15153
15154      // cond_AND_notInIT_T = and32(notInITt, condT)
15155      //                    = and32(1, 1)
15156      //                    = 1
15157      //
15158      // cond_AND_notInIT_T = newTemp(Ity_I32);
15159      // assign(cond_AND_notInIT_T,
15160      //        binop(Iop_And32, mkexpr(notInITt), mkexpr(condT)));
15161      cond_AND_notInIT_T = condT; /* 1 :: I32 */
15162
15163      /* END "partial eval { ITSTATE = 0; STANDARD_PREAMBLE; }" */
15164   } else {
15165      /* BEGIN { STANDARD PREAMBLE; } */
15166
15167      old_itstate = get_ITSTATE();
15168
15169      new_itstate = newTemp(Ity_I32);
15170      assign(new_itstate,
15171             binop(Iop_Shr32, mkexpr(old_itstate), mkU8(8)));
15172
15173      put_ITSTATE(new_itstate);
15174
15175      /* Same strategy as for ARM insns: generate a condition
15176         temporary at this point (or IRTemp_INVALID, meaning
15177         unconditional).  We leave it to lower-level instruction
15178         decoders to decide whether they can generate straight-line
15179         code, or whether they must generate a side exit before the
15180         instruction.  condT :: Ity_I32 and is always either zero or
15181         one. */
15182      IRTemp condT1 = newTemp(Ity_I32);
15183      assign(condT1,
15184             mk_armg_calculate_condition_dyn(
15185                binop(Iop_Xor32,
15186                      binop(Iop_And32, mkexpr(old_itstate), mkU32(0xF0)),
15187                      mkU32(0xE0))
15188            )
15189      );
15190
15191      /* This is a bit complex, but needed to make Memcheck understand
15192         that, if the condition in old_itstate[7:4] denotes AL (that
15193         is, if this instruction is to be executed unconditionally),
15194         then condT does not depend on the results of calling the
15195         helper.
15196
15197         We test explicitly for old_itstate[7:4] == AL ^ 0xE, and in
15198         that case set condT directly to 1.  Else we use the results
15199         of the helper.  Since old_itstate is always defined and
15200         because Memcheck does lazy V-bit propagation through Mux0X,
15201         this will cause condT to always be a defined 1 if the
15202         condition is 'AL'.  From an execution semantics point of view
15203         this is irrelevant since we're merely duplicating part of the
15204         behaviour of the helper.  But it makes it clear to Memcheck,
15205         in this case, that condT does not in fact depend on the
15206         contents of the condition code thunk.  Without it, we get
15207         quite a lot of false errors.
15208
15209         So, just to clarify: from a straight semantics point of view,
15210         we can simply do "assign(condT, mkexpr(condT1))", and the
15211         simulator still runs fine.  It's just that we get loads of
15212         false errors from Memcheck. */
15213      condT = newTemp(Ity_I32);
15214      assign(condT, IRExpr_Mux0X(
15215                       unop(Iop_32to8, binop(Iop_And32,
15216                                             mkexpr(old_itstate),
15217                                             mkU32(0xF0))),
15218                       mkU32(1),
15219                       mkexpr(condT1)
15220            ));
15221
15222      /* Something we don't have in ARM: generate a 0 or 1 value
15223         indicating whether or not we are in an IT block (NB: 0 = in
15224         IT block, 1 = not in IT block).  This is used to gate
15225         condition code updates in 16-bit Thumb instructions. */
15226      IRTemp notInITt = newTemp(Ity_I32);
15227      assign(notInITt,
15228             binop(Iop_Xor32,
15229                   binop(Iop_And32, mkexpr(old_itstate), mkU32(1)),
15230                   mkU32(1)));
15231
15232      /* Compute 'condT && notInITt' -- that is, the instruction is
15233         going to execute, and we're not in an IT block.  This is the
15234         gating condition for updating condition codes in 16-bit Thumb
15235         instructions, except for CMP, CMN and TST. */
15236      cond_AND_notInIT_T = newTemp(Ity_I32);
15237      assign(cond_AND_notInIT_T,
15238             binop(Iop_And32, mkexpr(notInITt), mkexpr(condT)));
15239      /* END { STANDARD PREAMBLE; } */
15240   }
15241
15242
15243   /* At this point:
15244      * ITSTATE has been updated
15245      * condT holds the guarding condition for this instruction (0 or 1),
15246      * notInITt is 1 if we're in "normal" code, 0 if in an IT block
15247      * cond_AND_notInIT_T is the AND of the above two.
15248
15249      If the instruction proper can't trap, then there's nothing else
15250      to do w.r.t. ITSTATE -- just go and and generate IR for the
15251      insn, taking into account the guarding condition.
15252
15253      If, however, the instruction might trap, then we must back up
15254      ITSTATE to the old value, and re-update it after the potentially
15255      trapping IR section.  A trap can happen either via a memory
15256      reference or because we need to throw SIGILL.
15257
15258      If an instruction has a side exit, we need to be sure that any
15259      ITSTATE backup is re-updated before the side exit.
15260   */
15261
15262   /* ----------------------------------------------------------- */
15263   /* --                                                       -- */
15264   /* -- Thumb 16-bit integer instructions                     -- */
15265   /* --                                                       -- */
15266   /* -- IMPORTANT: references to insn1 or INSN1 are           -- */
15267   /* --            not allowed in this section                -- */
15268   /* --                                                       -- */
15269   /* ----------------------------------------------------------- */
15270
15271   /* 16-bit instructions inside an IT block, apart from CMP, CMN and
15272      TST, do not set the condition codes.  Hence we must dynamically
15273      test for this case for every condition code update. */
15274
15275   IROp   anOp   = Iop_INVALID;
15276   HChar* anOpNm = NULL;
15277
15278   /* ================ 16-bit 15:6 cases ================ */
15279
15280   switch (INSN0(15,6)) {
15281
15282   case 0x10a:   // CMP
15283   case 0x10b: { // CMN
15284      /* ---------------- CMP Rn, Rm ---------------- */
15285      Bool   isCMN = INSN0(15,6) == 0x10b;
15286      UInt   rN    = INSN0(2,0);
15287      UInt   rM    = INSN0(5,3);
15288      IRTemp argL  = newTemp(Ity_I32);
15289      IRTemp argR  = newTemp(Ity_I32);
15290      assign( argL, getIRegT(rN) );
15291      assign( argR, getIRegT(rM) );
15292      /* Update flags regardless of whether in an IT block or not. */
15293      setFlags_D1_D2( isCMN ? ARMG_CC_OP_ADD : ARMG_CC_OP_SUB,
15294                      argL, argR, condT );
15295      DIP("%s r%u, r%u\n", isCMN ? "cmn" : "cmp", rN, rM);
15296      goto decode_success;
15297   }
15298
15299   case 0x108: {
15300      /* ---------------- TST Rn, Rm ---------------- */
15301      UInt   rN   = INSN0(2,0);
15302      UInt   rM   = INSN0(5,3);
15303      IRTemp oldC = newTemp(Ity_I32);
15304      IRTemp oldV = newTemp(Ity_I32);
15305      IRTemp res  = newTemp(Ity_I32);
15306      assign( oldC, mk_armg_calculate_flag_c() );
15307      assign( oldV, mk_armg_calculate_flag_v() );
15308      assign( res,  binop(Iop_And32, getIRegT(rN), getIRegT(rM)) );
15309      /* Update flags regardless of whether in an IT block or not. */
15310      setFlags_D1_D2_ND( ARMG_CC_OP_LOGIC, res, oldC, oldV, condT );
15311      DIP("tst r%u, r%u\n", rN, rM);
15312      goto decode_success;
15313   }
15314
15315   case 0x109: {
15316      /* ---------------- NEGS Rd, Rm ---------------- */
15317      /* Rd = -Rm */
15318      UInt   rM   = INSN0(5,3);
15319      UInt   rD   = INSN0(2,0);
15320      IRTemp arg  = newTemp(Ity_I32);
15321      IRTemp zero = newTemp(Ity_I32);
15322      assign(arg, getIRegT(rM));
15323      assign(zero, mkU32(0));
15324      // rD can never be r15
15325      putIRegT(rD, binop(Iop_Sub32, mkexpr(zero), mkexpr(arg)), condT);
15326      setFlags_D1_D2( ARMG_CC_OP_SUB, zero, arg, cond_AND_notInIT_T);
15327      DIP("negs r%u, r%u\n", rD, rM);
15328      goto decode_success;
15329   }
15330
15331   case 0x10F: {
15332      /* ---------------- MVNS Rd, Rm ---------------- */
15333      /* Rd = ~Rm */
15334      UInt   rM   = INSN0(5,3);
15335      UInt   rD   = INSN0(2,0);
15336      IRTemp oldV = newTemp(Ity_I32);
15337      IRTemp oldC = newTemp(Ity_I32);
15338      IRTemp res  = newTemp(Ity_I32);
15339      assign( oldV, mk_armg_calculate_flag_v() );
15340      assign( oldC, mk_armg_calculate_flag_c() );
15341      assign(res, unop(Iop_Not32, getIRegT(rM)));
15342      // rD can never be r15
15343      putIRegT(rD, mkexpr(res), condT);
15344      setFlags_D1_D2_ND( ARMG_CC_OP_LOGIC, res, oldC, oldV,
15345                         cond_AND_notInIT_T );
15346      DIP("mvns r%u, r%u\n", rD, rM);
15347      goto decode_success;
15348   }
15349
15350   case 0x10C:
15351      /* ---------------- ORRS Rd, Rm ---------------- */
15352      anOp = Iop_Or32; anOpNm = "orr"; goto and_orr_eor_mul;
15353   case 0x100:
15354      /* ---------------- ANDS Rd, Rm ---------------- */
15355      anOp = Iop_And32; anOpNm = "and"; goto and_orr_eor_mul;
15356   case 0x101:
15357      /* ---------------- EORS Rd, Rm ---------------- */
15358      anOp = Iop_Xor32; anOpNm = "eor"; goto and_orr_eor_mul;
15359   case 0x10d:
15360      /* ---------------- MULS Rd, Rm ---------------- */
15361      anOp = Iop_Mul32; anOpNm = "mul"; goto and_orr_eor_mul;
15362   and_orr_eor_mul: {
15363      /* Rd = Rd `op` Rm */
15364      UInt   rM   = INSN0(5,3);
15365      UInt   rD   = INSN0(2,0);
15366      IRTemp res  = newTemp(Ity_I32);
15367      IRTemp oldV = newTemp(Ity_I32);
15368      IRTemp oldC = newTemp(Ity_I32);
15369      assign( oldV, mk_armg_calculate_flag_v() );
15370      assign( oldC, mk_armg_calculate_flag_c() );
15371      assign( res, binop(anOp, getIRegT(rD), getIRegT(rM) ));
15372      // not safe to read guest state after here
15373      // rD can never be r15
15374      putIRegT(rD, mkexpr(res), condT);
15375      setFlags_D1_D2_ND( ARMG_CC_OP_LOGIC, res, oldC, oldV,
15376                         cond_AND_notInIT_T );
15377      DIP("%s r%u, r%u\n", anOpNm, rD, rM);
15378      goto decode_success;
15379   }
15380
15381   case 0x10E: {
15382      /* ---------------- BICS Rd, Rm ---------------- */
15383      /* Rd = Rd & ~Rm */
15384      UInt   rM   = INSN0(5,3);
15385      UInt   rD   = INSN0(2,0);
15386      IRTemp res  = newTemp(Ity_I32);
15387      IRTemp oldV = newTemp(Ity_I32);
15388      IRTemp oldC = newTemp(Ity_I32);
15389      assign( oldV, mk_armg_calculate_flag_v() );
15390      assign( oldC, mk_armg_calculate_flag_c() );
15391      assign( res, binop(Iop_And32, getIRegT(rD),
15392                                    unop(Iop_Not32, getIRegT(rM) )));
15393      // not safe to read guest state after here
15394      // rD can never be r15
15395      putIRegT(rD, mkexpr(res), condT);
15396      setFlags_D1_D2_ND( ARMG_CC_OP_LOGIC, res, oldC, oldV,
15397                         cond_AND_notInIT_T );
15398      DIP("bics r%u, r%u\n", rD, rM);
15399      goto decode_success;
15400   }
15401
15402   case 0x105: {
15403      /* ---------------- ADCS Rd, Rm ---------------- */
15404      /* Rd = Rd + Rm + oldC */
15405      UInt   rM   = INSN0(5,3);
15406      UInt   rD   = INSN0(2,0);
15407      IRTemp argL = newTemp(Ity_I32);
15408      IRTemp argR = newTemp(Ity_I32);
15409      IRTemp oldC = newTemp(Ity_I32);
15410      IRTemp res  = newTemp(Ity_I32);
15411      assign(argL, getIRegT(rD));
15412      assign(argR, getIRegT(rM));
15413      assign(oldC, mk_armg_calculate_flag_c());
15414      assign(res, binop(Iop_Add32,
15415                        binop(Iop_Add32, mkexpr(argL), mkexpr(argR)),
15416                        mkexpr(oldC)));
15417      // rD can never be r15
15418      putIRegT(rD, mkexpr(res), condT);
15419      setFlags_D1_D2_ND( ARMG_CC_OP_ADC, argL, argR, oldC,
15420                         cond_AND_notInIT_T );
15421      DIP("adcs r%u, r%u\n", rD, rM);
15422      goto decode_success;
15423   }
15424
15425   case 0x106: {
15426      /* ---------------- SBCS Rd, Rm ---------------- */
15427      /* Rd = Rd - Rm - (oldC ^ 1) */
15428      UInt   rM   = INSN0(5,3);
15429      UInt   rD   = INSN0(2,0);
15430      IRTemp argL = newTemp(Ity_I32);
15431      IRTemp argR = newTemp(Ity_I32);
15432      IRTemp oldC = newTemp(Ity_I32);
15433      IRTemp res  = newTemp(Ity_I32);
15434      assign(argL, getIRegT(rD));
15435      assign(argR, getIRegT(rM));
15436      assign(oldC, mk_armg_calculate_flag_c());
15437      assign(res, binop(Iop_Sub32,
15438                        binop(Iop_Sub32, mkexpr(argL), mkexpr(argR)),
15439                        binop(Iop_Xor32, mkexpr(oldC), mkU32(1))));
15440      // rD can never be r15
15441      putIRegT(rD, mkexpr(res), condT);
15442      setFlags_D1_D2_ND( ARMG_CC_OP_SBB, argL, argR, oldC,
15443                         cond_AND_notInIT_T );
15444      DIP("sbcs r%u, r%u\n", rD, rM);
15445      goto decode_success;
15446   }
15447
15448   case 0x2CB: {
15449      /* ---------------- UXTB Rd, Rm ---------------- */
15450      /* Rd = 8Uto32(Rm) */
15451      UInt rM = INSN0(5,3);
15452      UInt rD = INSN0(2,0);
15453      putIRegT(rD, binop(Iop_And32, getIRegT(rM), mkU32(0xFF)),
15454                   condT);
15455      DIP("uxtb r%u, r%u\n", rD, rM);
15456      goto decode_success;
15457   }
15458
15459   case 0x2C9: {
15460      /* ---------------- SXTB Rd, Rm ---------------- */
15461      /* Rd = 8Sto32(Rm) */
15462      UInt rM = INSN0(5,3);
15463      UInt rD = INSN0(2,0);
15464      putIRegT(rD, binop(Iop_Sar32,
15465                         binop(Iop_Shl32, getIRegT(rM), mkU8(24)),
15466                         mkU8(24)),
15467                   condT);
15468      DIP("sxtb r%u, r%u\n", rD, rM);
15469      goto decode_success;
15470   }
15471
15472   case 0x2CA: {
15473      /* ---------------- UXTH Rd, Rm ---------------- */
15474      /* Rd = 16Uto32(Rm) */
15475      UInt rM = INSN0(5,3);
15476      UInt rD = INSN0(2,0);
15477      putIRegT(rD, binop(Iop_And32, getIRegT(rM), mkU32(0xFFFF)),
15478                   condT);
15479      DIP("uxth r%u, r%u\n", rD, rM);
15480      goto decode_success;
15481   }
15482
15483   case 0x2C8: {
15484      /* ---------------- SXTH Rd, Rm ---------------- */
15485      /* Rd = 16Sto32(Rm) */
15486      UInt rM = INSN0(5,3);
15487      UInt rD = INSN0(2,0);
15488      putIRegT(rD, binop(Iop_Sar32,
15489                         binop(Iop_Shl32, getIRegT(rM), mkU8(16)),
15490                         mkU8(16)),
15491                   condT);
15492      DIP("sxth r%u, r%u\n", rD, rM);
15493      goto decode_success;
15494   }
15495
15496   case 0x102:   // LSLS
15497   case 0x103:   // LSRS
15498   case 0x104:   // ASRS
15499   case 0x107: { // RORS
15500      /* ---------------- LSLS Rs, Rd ---------------- */
15501      /* ---------------- LSRS Rs, Rd ---------------- */
15502      /* ---------------- ASRS Rs, Rd ---------------- */
15503      /* ---------------- RORS Rs, Rd ---------------- */
15504      /* Rd = Rd `op` Rs, and set flags */
15505      UInt   rS   = INSN0(5,3);
15506      UInt   rD   = INSN0(2,0);
15507      IRTemp oldV = newTemp(Ity_I32);
15508      IRTemp rDt  = newTemp(Ity_I32);
15509      IRTemp rSt  = newTemp(Ity_I32);
15510      IRTemp res  = newTemp(Ity_I32);
15511      IRTemp resC = newTemp(Ity_I32);
15512      HChar* wot  = "???";
15513      assign(rSt, getIRegT(rS));
15514      assign(rDt, getIRegT(rD));
15515      assign(oldV, mk_armg_calculate_flag_v());
15516      /* Does not appear to be the standard 'how' encoding. */
15517      switch (INSN0(15,6)) {
15518         case 0x102:
15519            compute_result_and_C_after_LSL_by_reg(
15520               dis_buf, &res, &resC, rDt, rSt, rD, rS
15521            );
15522            wot = "lsl";
15523            break;
15524         case 0x103:
15525            compute_result_and_C_after_LSR_by_reg(
15526               dis_buf, &res, &resC, rDt, rSt, rD, rS
15527            );
15528            wot = "lsr";
15529            break;
15530         case 0x104:
15531            compute_result_and_C_after_ASR_by_reg(
15532               dis_buf, &res, &resC, rDt, rSt, rD, rS
15533            );
15534            wot = "asr";
15535            break;
15536         case 0x107:
15537            compute_result_and_C_after_ROR_by_reg(
15538               dis_buf, &res, &resC, rDt, rSt, rD, rS
15539            );
15540            wot = "ror";
15541            break;
15542         default:
15543            /*NOTREACHED*/vassert(0);
15544      }
15545      // not safe to read guest state after this point
15546      putIRegT(rD, mkexpr(res), condT);
15547      setFlags_D1_D2_ND( ARMG_CC_OP_LOGIC, res, resC, oldV,
15548                         cond_AND_notInIT_T );
15549      DIP("%ss r%u, r%u\n", wot, rS, rD);
15550      goto decode_success;
15551   }
15552
15553   case 0x2E8:   // REV
15554   case 0x2E9: { // REV16
15555      /* ---------------- REV   Rd, Rm ---------------- */
15556      /* ---------------- REV16 Rd, Rm ---------------- */
15557      UInt rM = INSN0(5,3);
15558      UInt rD = INSN0(2,0);
15559      Bool isREV = INSN0(15,6) == 0x2E8;
15560      IRTemp arg = newTemp(Ity_I32);
15561      assign(arg, getIRegT(rM));
15562      IRTemp res = isREV ? gen_REV(arg) : gen_REV16(arg);
15563      putIRegT(rD, mkexpr(res), condT);
15564      DIP("rev%s r%u, r%u\n", isREV ? "" : "16", rD, rM);
15565      goto decode_success;
15566   }
15567
15568   default:
15569      break; /* examine the next shortest prefix */
15570
15571   }
15572
15573
15574   /* ================ 16-bit 15:7 cases ================ */
15575
15576   switch (INSN0(15,7)) {
15577
15578   case BITS9(1,0,1,1,0,0,0,0,0): {
15579      /* ------------ ADD SP, #imm7 * 4 ------------ */
15580      UInt uimm7 = INSN0(6,0);
15581      putIRegT(13, binop(Iop_Add32, getIRegT(13), mkU32(uimm7 * 4)),
15582                   condT);
15583      DIP("add sp, #%u\n", uimm7 * 4);
15584      goto decode_success;
15585   }
15586
15587   case BITS9(1,0,1,1,0,0,0,0,1): {
15588      /* ------------ SUB SP, #imm7 * 4 ------------ */
15589      UInt uimm7 = INSN0(6,0);
15590      putIRegT(13, binop(Iop_Sub32, getIRegT(13), mkU32(uimm7 * 4)),
15591                   condT);
15592      DIP("sub sp, #%u\n", uimm7 * 4);
15593      goto decode_success;
15594   }
15595
15596   case BITS9(0,1,0,0,0,1,1,1,0): {
15597      /* ---------------- BX rM ---------------- */
15598      /* Branch to reg, and optionally switch modes.  Reg contains a
15599         suitably encoded address therefore (w CPSR.T at the bottom).
15600         Have to special-case r15, as usual. */
15601      UInt rM = (INSN0(6,6) << 3) | INSN0(5,3);
15602      if (BITS3(0,0,0) == INSN0(2,0)) {
15603         IRTemp dst = newTemp(Ity_I32);
15604         gen_SIGILL_T_if_in_but_NLI_ITBlock(old_itstate, new_itstate);
15605         mk_skip_over_T16_if_cond_is_false(condT);
15606         condT = IRTemp_INVALID;
15607         // now uncond
15608         if (rM <= 14) {
15609            assign( dst, getIRegT(rM) );
15610         } else {
15611            vassert(rM == 15);
15612            assign( dst, mkU32(guest_R15_curr_instr_notENC + 4) );
15613         }
15614         llPutIReg(15, mkexpr(dst));
15615         dres.jk_StopHere = rM == 14 ? Ijk_Ret : Ijk_Boring;
15616         dres.whatNext    = Dis_StopHere;
15617         DIP("bx r%u (possibly switch to ARM mode)\n", rM);
15618         goto decode_success;
15619      }
15620      break;
15621   }
15622
15623   /* ---------------- BLX rM ---------------- */
15624   /* Branch and link to interworking address in rM. */
15625   case BITS9(0,1,0,0,0,1,1,1,1): {
15626      if (BITS3(0,0,0) == INSN0(2,0)) {
15627         UInt rM = (INSN0(6,6) << 3) | INSN0(5,3);
15628         IRTemp dst = newTemp(Ity_I32);
15629         if (rM <= 14) {
15630            gen_SIGILL_T_if_in_but_NLI_ITBlock(old_itstate, new_itstate);
15631            mk_skip_over_T16_if_cond_is_false(condT);
15632            condT = IRTemp_INVALID;
15633            // now uncond
15634            /* We're returning to Thumb code, hence "| 1" */
15635            assign( dst, getIRegT(rM) );
15636            putIRegT( 14, mkU32( (guest_R15_curr_instr_notENC + 2) | 1 ),
15637                          IRTemp_INVALID );
15638            llPutIReg(15, mkexpr(dst));
15639            dres.jk_StopHere = Ijk_Call;
15640            dres.whatNext    = Dis_StopHere;
15641            DIP("blx r%u (possibly switch to ARM mode)\n", rM);
15642            goto decode_success;
15643         }
15644         /* else unpredictable, fall through */
15645      }
15646      break;
15647   }
15648
15649   default:
15650      break; /* examine the next shortest prefix */
15651
15652   }
15653
15654
15655   /* ================ 16-bit 15:8 cases ================ */
15656
15657   switch (INSN0(15,8)) {
15658
15659   case BITS8(1,1,0,1,1,1,1,1): {
15660      /* ---------------- SVC ---------------- */
15661      UInt imm8 = INSN0(7,0);
15662      if (imm8 == 0) {
15663         /* A syscall.  We can't do this conditionally, hence: */
15664         mk_skip_over_T16_if_cond_is_false( condT );
15665         // FIXME: what if we have to back up and restart this insn?
15666         // then ITSTATE will be wrong (we'll have it as "used")
15667         // when it isn't.  Correct is to save ITSTATE in a
15668         // stash pseudo-reg, and back up from that if we have to
15669         // restart.
15670         // uncond after here
15671         llPutIReg(15, mkU32( (guest_R15_curr_instr_notENC + 2) | 1 ));
15672         dres.jk_StopHere = Ijk_Sys_syscall;
15673         dres.whatNext    = Dis_StopHere;
15674         DIP("svc #0x%08x\n", imm8);
15675         goto decode_success;
15676      }
15677      /* else fall through */
15678      break;
15679   }
15680
15681   case BITS8(0,1,0,0,0,1,0,0): {
15682      /* ---------------- ADD(HI) Rd, Rm ---------------- */
15683      UInt h1 = INSN0(7,7);
15684      UInt h2 = INSN0(6,6);
15685      UInt rM = (h2 << 3) | INSN0(5,3);
15686      UInt rD = (h1 << 3) | INSN0(2,0);
15687      //if (h1 == 0 && h2 == 0) { // Original T1 was more restrictive
15688      if (rD == 15 && rM == 15) {
15689         // then it's invalid
15690      } else {
15691         IRTemp res = newTemp(Ity_I32);
15692         assign( res, binop(Iop_Add32, getIRegT(rD), getIRegT(rM) ));
15693         if (rD != 15) {
15694            putIRegT( rD, mkexpr(res), condT );
15695         } else {
15696            /* Only allowed outside or last-in IT block; SIGILL if not so. */
15697            gen_SIGILL_T_if_in_but_NLI_ITBlock(old_itstate, new_itstate);
15698            /* jump over insn if not selected */
15699            mk_skip_over_T16_if_cond_is_false(condT);
15700            condT = IRTemp_INVALID;
15701            // now uncond
15702            /* non-interworking branch */
15703            irsb->next = binop(Iop_Or32, mkexpr(res), mkU32(1));
15704            irsb->jumpkind = Ijk_Boring;
15705            dres.whatNext = Dis_StopHere;
15706         }
15707         DIP("add(hi) r%u, r%u\n", rD, rM);
15708         goto decode_success;
15709      }
15710      break;
15711   }
15712
15713   case BITS8(0,1,0,0,0,1,0,1): {
15714      /* ---------------- CMP(HI) Rd, Rm ---------------- */
15715      UInt h1 = INSN0(7,7);
15716      UInt h2 = INSN0(6,6);
15717      UInt rM = (h2 << 3) | INSN0(5,3);
15718      UInt rN = (h1 << 3) | INSN0(2,0);
15719      if (h1 != 0 || h2 != 0) {
15720         IRTemp argL  = newTemp(Ity_I32);
15721         IRTemp argR  = newTemp(Ity_I32);
15722         assign( argL, getIRegT(rN) );
15723         assign( argR, getIRegT(rM) );
15724         /* Update flags regardless of whether in an IT block or not. */
15725         setFlags_D1_D2( ARMG_CC_OP_SUB, argL, argR, condT );
15726         DIP("cmphi r%u, r%u\n", rN, rM);
15727         goto decode_success;
15728      }
15729      break;
15730   }
15731
15732   case BITS8(0,1,0,0,0,1,1,0): {
15733      /* ---------------- MOV(HI) Rd, Rm ---------------- */
15734      UInt h1 = INSN0(7,7);
15735      UInt h2 = INSN0(6,6);
15736      UInt rM = (h2 << 3) | INSN0(5,3);
15737      UInt rD = (h1 << 3) | INSN0(2,0);
15738      /* The old ARM ARM seems to disallow the case where both Rd and
15739         Rm are "low" registers, but newer versions allow it. */
15740      if (1 /*h1 != 0 || h2 != 0*/) {
15741         IRTemp val = newTemp(Ity_I32);
15742         assign( val, getIRegT(rM) );
15743         if (rD != 15) {
15744            putIRegT( rD, mkexpr(val), condT );
15745         } else {
15746            /* Only allowed outside or last-in IT block; SIGILL if not so. */
15747            gen_SIGILL_T_if_in_but_NLI_ITBlock(old_itstate, new_itstate);
15748            /* jump over insn if not selected */
15749            mk_skip_over_T16_if_cond_is_false(condT);
15750            condT = IRTemp_INVALID;
15751            // now uncond
15752            /* non-interworking branch */
15753            llPutIReg(15, binop(Iop_Or32, mkexpr(val), mkU32(1)));
15754            dres.jk_StopHere = rM == 14 ? Ijk_Ret : Ijk_Boring;
15755            dres.whatNext    = Dis_StopHere;
15756         }
15757         DIP("mov r%u, r%u\n", rD, rM);
15758         goto decode_success;
15759      }
15760      break;
15761   }
15762
15763   case BITS8(1,0,1,1,1,1,1,1): {
15764      /* ---------------- IT (if-then) ---------------- */
15765      UInt firstcond = INSN0(7,4);
15766      UInt mask = INSN0(3,0);
15767      UInt newITSTATE = 0;
15768      /* This is the ITSTATE represented as described in
15769         libvex_guest_arm.h.  It is not the ARM ARM representation. */
15770      UChar c1 = '.';
15771      UChar c2 = '.';
15772      UChar c3 = '.';
15773      Bool valid = compute_ITSTATE( &newITSTATE, &c1, &c2, &c3,
15774                                    firstcond, mask );
15775      if (valid && firstcond != 0xF/*NV*/) {
15776         /* Not allowed in an IT block; SIGILL if so. */
15777         gen_SIGILL_T_if_in_ITBlock(old_itstate, new_itstate);
15778
15779         IRTemp t = newTemp(Ity_I32);
15780         assign(t, mkU32(newITSTATE));
15781         put_ITSTATE(t);
15782
15783         DIP("it%c%c%c %s\n", c1, c2, c3, nCC(firstcond));
15784         goto decode_success;
15785      }
15786      break;
15787   }
15788
15789   case BITS8(1,0,1,1,0,0,0,1):
15790   case BITS8(1,0,1,1,0,0,1,1):
15791   case BITS8(1,0,1,1,1,0,0,1):
15792   case BITS8(1,0,1,1,1,0,1,1): {
15793      /* ---------------- CB{N}Z ---------------- */
15794      UInt rN    = INSN0(2,0);
15795      UInt bOP   = INSN0(11,11);
15796      UInt imm32 = (INSN0(9,9) << 6) | (INSN0(7,3) << 1);
15797      gen_SIGILL_T_if_in_ITBlock(old_itstate, new_itstate);
15798      /* It's a conditional branch forward. */
15799      IRTemp kond = newTemp(Ity_I1);
15800      assign( kond, binop(bOP ? Iop_CmpNE32 : Iop_CmpEQ32,
15801                          getIRegT(rN), mkU32(0)) );
15802
15803      vassert(0 == (guest_R15_curr_instr_notENC & 1));
15804      /* Looks like the nearest insn we can branch to is the one after
15805         next.  That makes sense, as there's no point in being able to
15806         encode a conditional branch to the next instruction. */
15807      UInt dst = (guest_R15_curr_instr_notENC + 4 + imm32) | 1;
15808      stmt(IRStmt_Exit( mkexpr(kond),
15809                        Ijk_Boring,
15810                        IRConst_U32(toUInt(dst)),
15811                        OFFB_R15T ));
15812      DIP("cb%s r%u, 0x%x\n", bOP ? "nz" : "z", rN, dst - 1);
15813      goto decode_success;
15814   }
15815
15816   default:
15817      break; /* examine the next shortest prefix */
15818
15819   }
15820
15821
15822   /* ================ 16-bit 15:9 cases ================ */
15823
15824   switch (INSN0(15,9)) {
15825
15826   case BITS7(1,0,1,1,0,1,0): {
15827      /* ---------------- PUSH ---------------- */
15828      /* This is a bit like STMxx, but way simpler. Complications we
15829         don't have to deal with:
15830         * SP being one of the transferred registers
15831         * direction (increment vs decrement)
15832         * before-vs-after-ness
15833      */
15834      Int  i, nRegs;
15835      UInt bitR    = INSN0(8,8);
15836      UInt regList = INSN0(7,0);
15837      if (bitR) regList |= (1 << 14);
15838
15839      /* At least one register must be transferred, else result is
15840         UNPREDICTABLE. */
15841      if (regList != 0) {
15842         /* Since we can't generate a guaranteed non-trapping IR
15843            sequence, (1) jump over the insn if it is gated false, and
15844            (2) back out the ITSTATE update. */
15845         mk_skip_over_T16_if_cond_is_false(condT);
15846         condT = IRTemp_INVALID;
15847         put_ITSTATE(old_itstate);
15848         // now uncond
15849
15850         nRegs = 0;
15851         for (i = 0; i < 16; i++) {
15852            if ((regList & (1 << i)) != 0)
15853               nRegs++;
15854         }
15855         vassert(nRegs >= 1 && nRegs <= 9);
15856
15857         /* Move SP down first of all, so we're "covered".  And don't
15858            mess with its alignment. */
15859         IRTemp newSP = newTemp(Ity_I32);
15860         assign(newSP, binop(Iop_Sub32, getIRegT(13), mkU32(4 * nRegs)));
15861         putIRegT(13, mkexpr(newSP), IRTemp_INVALID);
15862
15863         /* Generate a transfer base address as a forced-aligned
15864            version of the final SP value. */
15865         IRTemp base = newTemp(Ity_I32);
15866         assign(base, binop(Iop_And32, mkexpr(newSP), mkU32(~3)));
15867
15868         /* Now the transfers */
15869         nRegs = 0;
15870         for (i = 0; i < 16; i++) {
15871            if ((regList & (1 << i)) != 0) {
15872               storeLE( binop(Iop_Add32, mkexpr(base), mkU32(4 * nRegs)),
15873                        getIRegT(i) );
15874               nRegs++;
15875            }
15876         }
15877
15878         /* Reinstate the ITSTATE update. */
15879         put_ITSTATE(new_itstate);
15880
15881         DIP("push {%s0x%04x}\n", bitR ? "lr," : "", regList & 0xFF);
15882         goto decode_success;
15883      }
15884      break;
15885   }
15886
15887   case BITS7(1,0,1,1,1,1,0): {
15888      /* ---------------- POP ---------------- */
15889      Int  i, nRegs;
15890      UInt bitR    = INSN0(8,8);
15891      UInt regList = INSN0(7,0);
15892
15893      /* At least one register must be transferred, else result is
15894         UNPREDICTABLE. */
15895      if (regList != 0 || bitR) {
15896         /* Since we can't generate a guaranteed non-trapping IR
15897            sequence, (1) jump over the insn if it is gated false, and
15898            (2) back out the ITSTATE update. */
15899         mk_skip_over_T16_if_cond_is_false(condT);
15900         condT = IRTemp_INVALID;
15901         put_ITSTATE(old_itstate);
15902         // now uncond
15903
15904         nRegs = 0;
15905         for (i = 0; i < 8; i++) {
15906            if ((regList & (1 << i)) != 0)
15907               nRegs++;
15908         }
15909         vassert(nRegs >= 0 && nRegs <= 8);
15910         vassert(bitR == 0 || bitR == 1);
15911
15912         IRTemp oldSP = newTemp(Ity_I32);
15913         assign(oldSP, getIRegT(13));
15914
15915         /* Generate a transfer base address as a forced-aligned
15916            version of the original SP value. */
15917         IRTemp base = newTemp(Ity_I32);
15918         assign(base, binop(Iop_And32, mkexpr(oldSP), mkU32(~3)));
15919
15920         /* Compute a new value for SP, but don't install it yet, so
15921            that we're "covered" until all the transfers are done.
15922            And don't mess with its alignment. */
15923         IRTemp newSP = newTemp(Ity_I32);
15924         assign(newSP, binop(Iop_Add32, mkexpr(oldSP),
15925                                        mkU32(4 * (nRegs + bitR))));
15926
15927         /* Now the transfers, not including PC */
15928         nRegs = 0;
15929         for (i = 0; i < 8; i++) {
15930            if ((regList & (1 << i)) != 0) {
15931               putIRegT(i, loadLE( Ity_I32,
15932                                   binop(Iop_Add32, mkexpr(base),
15933                                                    mkU32(4 * nRegs))),
15934                           IRTemp_INVALID );
15935               nRegs++;
15936            }
15937         }
15938
15939         IRTemp newPC = IRTemp_INVALID;
15940         if (bitR) {
15941            newPC = newTemp(Ity_I32);
15942            assign( newPC, loadLE( Ity_I32,
15943                                   binop(Iop_Add32, mkexpr(base),
15944                                                    mkU32(4 * nRegs))));
15945         }
15946
15947         /* Now we can safely install the new SP value */
15948         putIRegT(13, mkexpr(newSP), IRTemp_INVALID);
15949
15950         /* Reinstate the ITSTATE update. */
15951         put_ITSTATE(new_itstate);
15952
15953         /* now, do we also have to do a branch?  If so, it turns out
15954            that the new PC value is encoded exactly as we need it to
15955            be -- with CPSR.T in the bottom bit.  So we can simply use
15956            it as is, no need to mess with it.  Note, therefore, this
15957            is an interworking return. */
15958         if (bitR) {
15959            llPutIReg(15, mkexpr(newPC));
15960            dres.jk_StopHere = Ijk_Ret;
15961            dres.whatNext    = Dis_StopHere;
15962         }
15963
15964         DIP("pop {%s0x%04x}\n", bitR ? "pc," : "", regList & 0xFF);
15965         goto decode_success;
15966      }
15967      break;
15968   }
15969
15970   case BITS7(0,0,0,1,1,1,0):   /* ADDS */
15971   case BITS7(0,0,0,1,1,1,1): { /* SUBS */
15972      /* ---------------- ADDS Rd, Rn, #uimm3 ---------------- */
15973      /* ---------------- SUBS Rd, Rn, #uimm3 ---------------- */
15974      UInt   uimm3 = INSN0(8,6);
15975      UInt   rN    = INSN0(5,3);
15976      UInt   rD    = INSN0(2,0);
15977      UInt   isSub = INSN0(9,9);
15978      IRTemp argL  = newTemp(Ity_I32);
15979      IRTemp argR  = newTemp(Ity_I32);
15980      assign( argL, getIRegT(rN) );
15981      assign( argR, mkU32(uimm3) );
15982      putIRegT(rD, binop(isSub ? Iop_Sub32 : Iop_Add32,
15983                         mkexpr(argL), mkexpr(argR)),
15984                   condT);
15985      setFlags_D1_D2( isSub ? ARMG_CC_OP_SUB : ARMG_CC_OP_ADD,
15986                      argL, argR, cond_AND_notInIT_T );
15987      DIP("%s r%u, r%u, #%u\n", isSub ? "subs" : "adds", rD, rN, uimm3);
15988      goto decode_success;
15989   }
15990
15991   case BITS7(0,0,0,1,1,0,0):   /* ADDS */
15992   case BITS7(0,0,0,1,1,0,1): { /* SUBS */
15993      /* ---------------- ADDS Rd, Rn, Rm ---------------- */
15994      /* ---------------- SUBS Rd, Rn, Rm ---------------- */
15995      UInt   rM    = INSN0(8,6);
15996      UInt   rN    = INSN0(5,3);
15997      UInt   rD    = INSN0(2,0);
15998      UInt   isSub = INSN0(9,9);
15999      IRTemp argL  = newTemp(Ity_I32);
16000      IRTemp argR  = newTemp(Ity_I32);
16001      assign( argL, getIRegT(rN) );
16002      assign( argR, getIRegT(rM) );
16003      putIRegT( rD, binop(isSub ? Iop_Sub32 : Iop_Add32,
16004                          mkexpr(argL), mkexpr(argR)),
16005                    condT );
16006      setFlags_D1_D2( isSub ? ARMG_CC_OP_SUB : ARMG_CC_OP_ADD,
16007                      argL, argR, cond_AND_notInIT_T );
16008      DIP("%s r%u, r%u, r%u\n", isSub ? "subs" : "adds", rD, rN, rM);
16009      goto decode_success;
16010   }
16011
16012   case BITS7(0,1,0,1,0,0,0):   /* STR */
16013   case BITS7(0,1,0,1,1,0,0): { /* LDR */
16014      /* ------------- LDR Rd, [Rn, Rm] ------------- */
16015      /* ------------- STR Rd, [Rn, Rm] ------------- */
16016      /* LDR/STR Rd, [Rn + Rm] */
16017      UInt    rD   = INSN0(2,0);
16018      UInt    rN   = INSN0(5,3);
16019      UInt    rM   = INSN0(8,6);
16020      UInt    isLD = INSN0(11,11);
16021
16022      mk_skip_over_T16_if_cond_is_false(condT);
16023      condT = IRTemp_INVALID;
16024      // now uncond
16025
16026      IRExpr* ea = binop(Iop_Add32, getIRegT(rN), getIRegT(rM));
16027      put_ITSTATE(old_itstate); // backout
16028      if (isLD) {
16029         putIRegT(rD, loadLE(Ity_I32, ea), IRTemp_INVALID);
16030      } else {
16031         storeLE(ea, getIRegT(rD));
16032      }
16033      put_ITSTATE(new_itstate); // restore
16034
16035      DIP("%s r%u, [r%u, r%u]\n", isLD ? "ldr" : "str", rD, rN, rM);
16036      goto decode_success;
16037   }
16038
16039   case BITS7(0,1,0,1,0,0,1):
16040   case BITS7(0,1,0,1,1,0,1): {
16041      /* ------------- LDRH Rd, [Rn, Rm] ------------- */
16042      /* ------------- STRH Rd, [Rn, Rm] ------------- */
16043      /* LDRH/STRH Rd, [Rn + Rm] */
16044      UInt    rD   = INSN0(2,0);
16045      UInt    rN   = INSN0(5,3);
16046      UInt    rM   = INSN0(8,6);
16047      UInt    isLD = INSN0(11,11);
16048
16049      mk_skip_over_T16_if_cond_is_false(condT);
16050      condT = IRTemp_INVALID;
16051      // now uncond
16052
16053      IRExpr* ea = binop(Iop_Add32, getIRegT(rN), getIRegT(rM));
16054      put_ITSTATE(old_itstate); // backout
16055      if (isLD) {
16056         putIRegT(rD, unop(Iop_16Uto32, loadLE(Ity_I16, ea)),
16057                      IRTemp_INVALID);
16058      } else {
16059         storeLE( ea, unop(Iop_32to16, getIRegT(rD)) );
16060      }
16061      put_ITSTATE(new_itstate); // restore
16062
16063      DIP("%sh r%u, [r%u, r%u]\n", isLD ? "ldr" : "str", rD, rN, rM);
16064      goto decode_success;
16065   }
16066
16067   case BITS7(0,1,0,1,1,1,1): {
16068      /* ------------- LDRSH Rd, [Rn, Rm] ------------- */
16069      /* LDRSH Rd, [Rn + Rm] */
16070      UInt    rD = INSN0(2,0);
16071      UInt    rN = INSN0(5,3);
16072      UInt    rM = INSN0(8,6);
16073
16074      mk_skip_over_T16_if_cond_is_false(condT);
16075      condT = IRTemp_INVALID;
16076      // now uncond
16077
16078      IRExpr* ea = binop(Iop_Add32, getIRegT(rN), getIRegT(rM));
16079      put_ITSTATE(old_itstate); // backout
16080      putIRegT(rD, unop(Iop_16Sto32, loadLE(Ity_I16, ea)),
16081                   IRTemp_INVALID);
16082      put_ITSTATE(new_itstate); // restore
16083
16084      DIP("ldrsh r%u, [r%u, r%u]\n", rD, rN, rM);
16085      goto decode_success;
16086   }
16087
16088   case BITS7(0,1,0,1,0,1,1): {
16089      /* ------------- LDRSB Rd, [Rn, Rm] ------------- */
16090      /* LDRSB Rd, [Rn + Rm] */
16091      UInt    rD = INSN0(2,0);
16092      UInt    rN = INSN0(5,3);
16093      UInt    rM = INSN0(8,6);
16094
16095      mk_skip_over_T16_if_cond_is_false(condT);
16096      condT = IRTemp_INVALID;
16097      // now uncond
16098
16099      IRExpr* ea = binop(Iop_Add32, getIRegT(rN), getIRegT(rM));
16100      put_ITSTATE(old_itstate); // backout
16101      putIRegT(rD, unop(Iop_8Sto32, loadLE(Ity_I8, ea)),
16102                   IRTemp_INVALID);
16103      put_ITSTATE(new_itstate); // restore
16104
16105      DIP("ldrsb r%u, [r%u, r%u]\n", rD, rN, rM);
16106      goto decode_success;
16107   }
16108
16109   case BITS7(0,1,0,1,0,1,0):
16110   case BITS7(0,1,0,1,1,1,0): {
16111      /* ------------- LDRB Rd, [Rn, Rm] ------------- */
16112      /* ------------- STRB Rd, [Rn, Rm] ------------- */
16113      /* LDRB/STRB Rd, [Rn + Rm] */
16114      UInt    rD   = INSN0(2,0);
16115      UInt    rN   = INSN0(5,3);
16116      UInt    rM   = INSN0(8,6);
16117      UInt    isLD = INSN0(11,11);
16118
16119      mk_skip_over_T16_if_cond_is_false(condT);
16120      condT = IRTemp_INVALID;
16121      // now uncond
16122
16123      IRExpr* ea = binop(Iop_Add32, getIRegT(rN), getIRegT(rM));
16124      put_ITSTATE(old_itstate); // backout
16125      if (isLD) {
16126         putIRegT(rD, unop(Iop_8Uto32, loadLE(Ity_I8, ea)),
16127                  IRTemp_INVALID);
16128      } else {
16129         storeLE( ea, unop(Iop_32to8, getIRegT(rD)) );
16130      }
16131      put_ITSTATE(new_itstate); // restore
16132
16133      DIP("%sb r%u, [r%u, r%u]\n", isLD ? "ldr" : "str", rD, rN, rM);
16134      goto decode_success;
16135   }
16136
16137   default:
16138      break; /* examine the next shortest prefix */
16139
16140   }
16141
16142
16143   /* ================ 16-bit 15:11 cases ================ */
16144
16145   switch (INSN0(15,11)) {
16146
16147   case BITS5(0,0,1,1,0):
16148   case BITS5(0,0,1,1,1): {
16149      /* ---------------- ADDS Rn, #uimm8 ---------------- */
16150      /* ---------------- SUBS Rn, #uimm8 ---------------- */
16151      UInt   isSub = INSN0(11,11);
16152      UInt   rN    = INSN0(10,8);
16153      UInt   uimm8 = INSN0(7,0);
16154      IRTemp argL  = newTemp(Ity_I32);
16155      IRTemp argR  = newTemp(Ity_I32);
16156      assign( argL, getIRegT(rN) );
16157      assign( argR, mkU32(uimm8) );
16158      putIRegT( rN, binop(isSub ? Iop_Sub32 : Iop_Add32,
16159                          mkexpr(argL), mkexpr(argR)), condT );
16160      setFlags_D1_D2( isSub ? ARMG_CC_OP_SUB : ARMG_CC_OP_ADD,
16161                      argL, argR, cond_AND_notInIT_T );
16162      DIP("%s r%u, #%u\n", isSub ? "subs" : "adds", rN, uimm8);
16163      goto decode_success;
16164   }
16165
16166   case BITS5(1,0,1,0,0): {
16167      /* ---------------- ADD rD, PC, #imm8 * 4 ---------------- */
16168      /* a.k.a. ADR */
16169      /* rD = align4(PC) + imm8 * 4 */
16170      UInt rD   = INSN0(10,8);
16171      UInt imm8 = INSN0(7,0);
16172      putIRegT(rD, binop(Iop_Add32,
16173                         binop(Iop_And32, getIRegT(15), mkU32(~3U)),
16174                         mkU32(imm8 * 4)),
16175                   condT);
16176      DIP("add r%u, pc, #%u\n", rD, imm8 * 4);
16177      goto decode_success;
16178   }
16179
16180   case BITS5(1,0,1,0,1): {
16181      /* ---------------- ADD rD, SP, #imm8 * 4 ---------------- */
16182      UInt rD   = INSN0(10,8);
16183      UInt imm8 = INSN0(7,0);
16184      putIRegT(rD, binop(Iop_Add32, getIRegT(13), mkU32(imm8 * 4)),
16185                   condT);
16186      DIP("add r%u, r13, #%u\n", rD, imm8 * 4);
16187      goto decode_success;
16188   }
16189
16190   case BITS5(0,0,1,0,1): {
16191      /* ---------------- CMP Rn, #uimm8 ---------------- */
16192      UInt   rN    = INSN0(10,8);
16193      UInt   uimm8 = INSN0(7,0);
16194      IRTemp argL  = newTemp(Ity_I32);
16195      IRTemp argR  = newTemp(Ity_I32);
16196      assign( argL, getIRegT(rN) );
16197      assign( argR, mkU32(uimm8) );
16198      /* Update flags regardless of whether in an IT block or not. */
16199      setFlags_D1_D2( ARMG_CC_OP_SUB, argL, argR, condT );
16200      DIP("cmp r%u, #%u\n", rN, uimm8);
16201      goto decode_success;
16202   }
16203
16204   case BITS5(0,0,1,0,0): {
16205      /* -------------- (T1) MOVS Rn, #uimm8 -------------- */
16206      UInt   rD    = INSN0(10,8);
16207      UInt   uimm8 = INSN0(7,0);
16208      IRTemp oldV  = newTemp(Ity_I32);
16209      IRTemp oldC  = newTemp(Ity_I32);
16210      IRTemp res   = newTemp(Ity_I32);
16211      assign( oldV, mk_armg_calculate_flag_v() );
16212      assign( oldC, mk_armg_calculate_flag_c() );
16213      assign( res, mkU32(uimm8) );
16214      putIRegT(rD, mkexpr(res), condT);
16215      setFlags_D1_D2_ND( ARMG_CC_OP_LOGIC, res, oldC, oldV,
16216                         cond_AND_notInIT_T );
16217      DIP("movs r%u, #%u\n", rD, uimm8);
16218      goto decode_success;
16219   }
16220
16221   case BITS5(0,1,0,0,1): {
16222      /* ------------- LDR Rd, [PC, #imm8 * 4] ------------- */
16223      /* LDR Rd, [align4(PC) + imm8 * 4] */
16224      UInt   rD   = INSN0(10,8);
16225      UInt   imm8 = INSN0(7,0);
16226      IRTemp ea   = newTemp(Ity_I32);
16227
16228      mk_skip_over_T16_if_cond_is_false(condT);
16229      condT = IRTemp_INVALID;
16230      // now uncond
16231
16232      assign(ea, binop(Iop_Add32,
16233                       binop(Iop_And32, getIRegT(15), mkU32(~3U)),
16234                       mkU32(imm8 * 4)));
16235      put_ITSTATE(old_itstate); // backout
16236      putIRegT(rD, loadLE(Ity_I32, mkexpr(ea)),
16237                   IRTemp_INVALID);
16238      put_ITSTATE(new_itstate); // restore
16239
16240      DIP("ldr r%u, [pc, #%u]\n", rD, imm8 * 4);
16241      goto decode_success;
16242   }
16243
16244   case BITS5(0,1,1,0,0):   /* STR */
16245   case BITS5(0,1,1,0,1): { /* LDR */
16246      /* ------------- LDR Rd, [Rn, #imm5 * 4] ------------- */
16247      /* ------------- STR Rd, [Rn, #imm5 * 4] ------------- */
16248      /* LDR/STR Rd, [Rn + imm5 * 4] */
16249      UInt    rD   = INSN0(2,0);
16250      UInt    rN   = INSN0(5,3);
16251      UInt    imm5 = INSN0(10,6);
16252      UInt    isLD = INSN0(11,11);
16253
16254      mk_skip_over_T16_if_cond_is_false(condT);
16255      condT = IRTemp_INVALID;
16256      // now uncond
16257
16258      IRExpr* ea = binop(Iop_Add32, getIRegT(rN), mkU32(imm5 * 4));
16259      put_ITSTATE(old_itstate); // backout
16260      if (isLD) {
16261         putIRegT(rD, loadLE(Ity_I32, ea), IRTemp_INVALID);
16262      } else {
16263         storeLE( ea, getIRegT(rD) );
16264      }
16265      put_ITSTATE(new_itstate); // restore
16266
16267      DIP("%s r%u, [r%u, #%u]\n", isLD ? "ldr" : "str", rD, rN, imm5 * 4);
16268      goto decode_success;
16269   }
16270
16271   case BITS5(1,0,0,0,0):   /* STRH */
16272   case BITS5(1,0,0,0,1): { /* LDRH */
16273      /* ------------- LDRH Rd, [Rn, #imm5 * 2] ------------- */
16274      /* ------------- STRH Rd, [Rn, #imm5 * 2] ------------- */
16275      /* LDRH/STRH Rd, [Rn + imm5 * 2] */
16276      UInt    rD   = INSN0(2,0);
16277      UInt    rN   = INSN0(5,3);
16278      UInt    imm5 = INSN0(10,6);
16279      UInt    isLD = INSN0(11,11);
16280
16281      mk_skip_over_T16_if_cond_is_false(condT);
16282      condT = IRTemp_INVALID;
16283      // now uncond
16284
16285      IRExpr* ea = binop(Iop_Add32, getIRegT(rN), mkU32(imm5 * 2));
16286      put_ITSTATE(old_itstate); // backout
16287      if (isLD) {
16288         putIRegT(rD, unop(Iop_16Uto32, loadLE(Ity_I16, ea)),
16289                  IRTemp_INVALID);
16290      } else {
16291         storeLE( ea, unop(Iop_32to16, getIRegT(rD)) );
16292      }
16293      put_ITSTATE(new_itstate); // restore
16294
16295      DIP("%sh r%u, [r%u, #%u]\n", isLD ? "ldr" : "str", rD, rN, imm5 * 2);
16296      goto decode_success;
16297   }
16298
16299   case BITS5(0,1,1,1,0):   /* STRB */
16300   case BITS5(0,1,1,1,1): { /* LDRB */
16301      /* ------------- LDRB Rd, [Rn, #imm5] ------------- */
16302      /* ------------- STRB Rd, [Rn, #imm5] ------------- */
16303      /* LDRB/STRB Rd, [Rn + imm5] */
16304      UInt    rD   = INSN0(2,0);
16305      UInt    rN   = INSN0(5,3);
16306      UInt    imm5 = INSN0(10,6);
16307      UInt    isLD = INSN0(11,11);
16308
16309      mk_skip_over_T16_if_cond_is_false(condT);
16310      condT = IRTemp_INVALID;
16311      // now uncond
16312
16313      IRExpr* ea = binop(Iop_Add32, getIRegT(rN), mkU32(imm5));
16314      put_ITSTATE(old_itstate); // backout
16315      if (isLD) {
16316         putIRegT(rD, unop(Iop_8Uto32, loadLE(Ity_I8, ea)),
16317                  IRTemp_INVALID);
16318      } else {
16319         storeLE( ea, unop(Iop_32to8, getIRegT(rD)) );
16320      }
16321      put_ITSTATE(new_itstate); // restore
16322
16323      DIP("%sb r%u, [r%u, #%u]\n", isLD ? "ldr" : "str", rD, rN, imm5);
16324      goto decode_success;
16325   }
16326
16327   case BITS5(1,0,0,1,0):   /* STR */
16328   case BITS5(1,0,0,1,1): { /* LDR */
16329      /* ------------- LDR Rd, [SP, #imm8 * 4] ------------- */
16330      /* ------------- STR Rd, [SP, #imm8 * 4] ------------- */
16331      /* LDR/STR Rd, [SP + imm8 * 4] */
16332      UInt rD    = INSN0(10,8);
16333      UInt imm8  = INSN0(7,0);
16334      UInt isLD  = INSN0(11,11);
16335
16336      mk_skip_over_T16_if_cond_is_false(condT);
16337      condT = IRTemp_INVALID;
16338      // now uncond
16339
16340      IRExpr* ea = binop(Iop_Add32, getIRegT(13), mkU32(imm8 * 4));
16341      put_ITSTATE(old_itstate); // backout
16342      if (isLD) {
16343         putIRegT(rD, loadLE(Ity_I32, ea), IRTemp_INVALID);
16344      } else {
16345         storeLE(ea, getIRegT(rD));
16346      }
16347      put_ITSTATE(new_itstate); // restore
16348
16349      DIP("%s r%u, [sp, #%u]\n", isLD ? "ldr" : "str", rD, imm8 * 4);
16350      goto decode_success;
16351   }
16352
16353   case BITS5(1,1,0,0,1): {
16354      /* ------------- LDMIA Rn!, {reglist} ------------- */
16355      Int i, nRegs = 0;
16356      UInt rN   = INSN0(10,8);
16357      UInt list = INSN0(7,0);
16358      /* Empty lists aren't allowed. */
16359      if (list != 0) {
16360         mk_skip_over_T16_if_cond_is_false(condT);
16361         condT = IRTemp_INVALID;
16362         put_ITSTATE(old_itstate);
16363         // now uncond
16364
16365         IRTemp oldRn = newTemp(Ity_I32);
16366         IRTemp base  = newTemp(Ity_I32);
16367         assign(oldRn, getIRegT(rN));
16368         assign(base, binop(Iop_And32, mkexpr(oldRn), mkU32(~3U)));
16369         for (i = 0; i < 8; i++) {
16370            if (0 == (list & (1 << i)))
16371               continue;
16372            nRegs++;
16373            putIRegT(
16374               i, loadLE(Ity_I32,
16375                         binop(Iop_Add32, mkexpr(base),
16376                                          mkU32(nRegs * 4 - 4))),
16377               IRTemp_INVALID
16378            );
16379         }
16380         /* Only do the writeback for rN if it isn't in the list of
16381            registers to be transferred. */
16382         if (0 == (list & (1 << rN))) {
16383            putIRegT(rN,
16384                     binop(Iop_Add32, mkexpr(oldRn),
16385                                      mkU32(nRegs * 4)),
16386                     IRTemp_INVALID
16387            );
16388         }
16389
16390         /* Reinstate the ITSTATE update. */
16391         put_ITSTATE(new_itstate);
16392
16393         DIP("ldmia r%u!, {0x%04x}\n", rN, list);
16394         goto decode_success;
16395      }
16396      break;
16397   }
16398
16399   case BITS5(1,1,0,0,0): {
16400      /* ------------- STMIA Rn!, {reglist} ------------- */
16401      Int i, nRegs = 0;
16402      UInt rN   = INSN0(10,8);
16403      UInt list = INSN0(7,0);
16404      /* Empty lists aren't allowed.  Also, if rN is in the list then
16405         it must be the lowest numbered register in the list. */
16406      Bool valid = list != 0;
16407      if (valid && 0 != (list & (1 << rN))) {
16408         for (i = 0; i < rN; i++) {
16409            if (0 != (list & (1 << i)))
16410               valid = False;
16411         }
16412      }
16413      if (valid) {
16414         mk_skip_over_T16_if_cond_is_false(condT);
16415         condT = IRTemp_INVALID;
16416         put_ITSTATE(old_itstate);
16417         // now uncond
16418
16419         IRTemp oldRn = newTemp(Ity_I32);
16420         IRTemp base = newTemp(Ity_I32);
16421         assign(oldRn, getIRegT(rN));
16422         assign(base, binop(Iop_And32, mkexpr(oldRn), mkU32(~3U)));
16423         for (i = 0; i < 8; i++) {
16424            if (0 == (list & (1 << i)))
16425               continue;
16426            nRegs++;
16427            storeLE( binop(Iop_Add32, mkexpr(base), mkU32(nRegs * 4 - 4)),
16428                     getIRegT(i) );
16429         }
16430         /* Always do the writeback. */
16431         putIRegT(rN,
16432                  binop(Iop_Add32, mkexpr(oldRn),
16433                                   mkU32(nRegs * 4)),
16434                  IRTemp_INVALID);
16435
16436         /* Reinstate the ITSTATE update. */
16437         put_ITSTATE(new_itstate);
16438
16439         DIP("stmia r%u!, {0x%04x}\n", rN, list);
16440         goto decode_success;
16441      }
16442      break;
16443   }
16444
16445   case BITS5(0,0,0,0,0):   /* LSLS */
16446   case BITS5(0,0,0,0,1):   /* LSRS */
16447   case BITS5(0,0,0,1,0): { /* ASRS */
16448      /* ---------------- LSLS Rd, Rm, #imm5 ---------------- */
16449      /* ---------------- LSRS Rd, Rm, #imm5 ---------------- */
16450      /* ---------------- ASRS Rd, Rm, #imm5 ---------------- */
16451      UInt   rD   = INSN0(2,0);
16452      UInt   rM   = INSN0(5,3);
16453      UInt   imm5 = INSN0(10,6);
16454      IRTemp res  = newTemp(Ity_I32);
16455      IRTemp resC = newTemp(Ity_I32);
16456      IRTemp rMt  = newTemp(Ity_I32);
16457      IRTemp oldV = newTemp(Ity_I32);
16458      HChar* wot  = "???";
16459      assign(rMt, getIRegT(rM));
16460      assign(oldV, mk_armg_calculate_flag_v());
16461      /* Looks like INSN0(12,11) are the standard 'how' encoding.
16462         Could compactify if the ROR case later appears. */
16463      switch (INSN0(15,11)) {
16464         case BITS5(0,0,0,0,0):
16465            compute_result_and_C_after_LSL_by_imm5(
16466               dis_buf, &res, &resC, rMt, imm5, rM
16467            );
16468            wot = "lsl";
16469            break;
16470         case BITS5(0,0,0,0,1):
16471            compute_result_and_C_after_LSR_by_imm5(
16472               dis_buf, &res, &resC, rMt, imm5, rM
16473            );
16474            wot = "lsr";
16475            break;
16476         case BITS5(0,0,0,1,0):
16477            compute_result_and_C_after_ASR_by_imm5(
16478               dis_buf, &res, &resC, rMt, imm5, rM
16479            );
16480            wot = "asr";
16481            break;
16482         default:
16483            /*NOTREACHED*/vassert(0);
16484      }
16485      // not safe to read guest state after this point
16486      putIRegT(rD, mkexpr(res), condT);
16487      setFlags_D1_D2_ND( ARMG_CC_OP_LOGIC, res, resC, oldV,
16488                         cond_AND_notInIT_T );
16489      /* ignore buf and roll our own output */
16490      DIP("%ss r%u, r%u, #%u\n", wot, rD, rM, imm5);
16491      goto decode_success;
16492   }
16493
16494   case BITS5(1,1,1,0,0): {
16495      /* ---------------- B #simm11 ---------------- */
16496      Int  simm11 = INSN0(10,0);
16497           simm11 = (simm11 << 21) >> 20;
16498      UInt dst    = simm11 + guest_R15_curr_instr_notENC + 4;
16499      /* Only allowed outside or last-in IT block; SIGILL if not so. */
16500      gen_SIGILL_T_if_in_but_NLI_ITBlock(old_itstate, new_itstate);
16501      // and skip this insn if not selected; being cleverer is too
16502      // difficult
16503      mk_skip_over_T16_if_cond_is_false(condT);
16504      condT = IRTemp_INVALID;
16505      // now uncond
16506      llPutIReg(15, mkU32( dst | 1 /*CPSR.T*/ ));
16507      dres.jk_StopHere = Ijk_Boring;
16508      dres.whatNext    = Dis_StopHere;
16509      DIP("b 0x%x\n", dst);
16510      goto decode_success;
16511   }
16512
16513   default:
16514      break; /* examine the next shortest prefix */
16515
16516   }
16517
16518
16519   /* ================ 16-bit 15:12 cases ================ */
16520
16521   switch (INSN0(15,12)) {
16522
16523   case BITS4(1,1,0,1): {
16524      /* ---------------- Bcond #simm8 ---------------- */
16525      UInt cond  = INSN0(11,8);
16526      Int  simm8 = INSN0(7,0);
16527           simm8 = (simm8 << 24) >> 23;
16528      UInt dst   = simm8 + guest_R15_curr_instr_notENC + 4;
16529      if (cond != ARMCondAL && cond != ARMCondNV) {
16530         /* Not allowed in an IT block; SIGILL if so. */
16531         gen_SIGILL_T_if_in_ITBlock(old_itstate, new_itstate);
16532
16533         IRTemp kondT = newTemp(Ity_I32);
16534         assign( kondT, mk_armg_calculate_condition(cond) );
16535         stmt( IRStmt_Exit( unop(Iop_32to1, mkexpr(kondT)),
16536                            Ijk_Boring,
16537                            IRConst_U32(dst | 1/*CPSR.T*/),
16538                            OFFB_R15T ));
16539         llPutIReg(15, mkU32( (guest_R15_curr_instr_notENC + 2)
16540                              | 1 /*CPSR.T*/ ));
16541         dres.jk_StopHere = Ijk_Boring;
16542         dres.whatNext    = Dis_StopHere;
16543         DIP("b%s 0x%x\n", nCC(cond), dst);
16544         goto decode_success;
16545      }
16546      break;
16547   }
16548
16549   default:
16550      break; /* hmm, nothing matched */
16551
16552   }
16553
16554   /* ================ 16-bit misc cases ================ */
16555
16556   /* ------ NOP ------ */
16557   if (INSN0(15,0) == 0xBF00) {
16558      DIP("nop");
16559      goto decode_success;
16560   }
16561
16562   /* ----------------------------------------------------------- */
16563   /* --                                                       -- */
16564   /* -- Thumb 32-bit integer instructions                     -- */
16565   /* --                                                       -- */
16566   /* ----------------------------------------------------------- */
16567
16568#  define INSN1(_bMax,_bMin)  SLICE_UInt(((UInt)insn1), (_bMax), (_bMin))
16569
16570   /* second 16 bits of the instruction, if any */
16571   vassert(insn1 == 0);
16572   insn1 = getUShortLittleEndianly( guest_instr+2 );
16573
16574   anOp   = Iop_INVALID; /* paranoia */
16575   anOpNm = NULL;        /* paranoia */
16576
16577   /* Change result defaults to suit 32-bit insns. */
16578   vassert(dres.whatNext   == Dis_Continue);
16579   vassert(dres.len        == 2);
16580   vassert(dres.continueAt == 0);
16581   dres.len = 4;
16582
16583   /* ---------------- BL/BLX simm26 ---------------- */
16584   if (BITS5(1,1,1,1,0) == INSN0(15,11) && BITS2(1,1) == INSN1(15,14)) {
16585      UInt isBL = INSN1(12,12);
16586      UInt bS   = INSN0(10,10);
16587      UInt bJ1  = INSN1(13,13);
16588      UInt bJ2  = INSN1(11,11);
16589      UInt bI1  = 1 ^ (bJ1 ^ bS);
16590      UInt bI2  = 1 ^ (bJ2 ^ bS);
16591      Int simm25
16592         =   (bS          << (1 + 1 + 10 + 11 + 1))
16593           | (bI1         << (1 + 10 + 11 + 1))
16594           | (bI2         << (10 + 11 + 1))
16595           | (INSN0(9,0)  << (11 + 1))
16596           | (INSN1(10,0) << 1);
16597      simm25 = (simm25 << 7) >> 7;
16598
16599      vassert(0 == (guest_R15_curr_instr_notENC & 1));
16600      UInt dst = simm25 + guest_R15_curr_instr_notENC + 4;
16601
16602      /* One further validity case to check: in the case of BLX
16603         (not-BL), that insn1[0] must be zero. */
16604      Bool valid = True;
16605      if (isBL == 0 && INSN1(0,0) == 1) valid = False;
16606      if (valid) {
16607         /* Only allowed outside or last-in IT block; SIGILL if not so. */
16608         gen_SIGILL_T_if_in_but_NLI_ITBlock(old_itstate, new_itstate);
16609         // and skip this insn if not selected; being cleverer is too
16610         // difficult
16611         mk_skip_over_T32_if_cond_is_false(condT);
16612         condT = IRTemp_INVALID;
16613         // now uncond
16614
16615         /* We're returning to Thumb code, hence "| 1" */
16616         putIRegT( 14, mkU32( (guest_R15_curr_instr_notENC + 4) | 1 ),
16617                   IRTemp_INVALID);
16618         if (isBL) {
16619            /* BL: unconditional T -> T call */
16620            /* we're calling Thumb code, hence "| 1" */
16621            llPutIReg(15, mkU32( dst | 1 ));
16622            DIP("bl 0x%x (stay in Thumb mode)\n", dst);
16623         } else {
16624            /* BLX: unconditional T -> A call */
16625            /* we're calling ARM code, hence "& 3" to align to a
16626               valid ARM insn address */
16627            llPutIReg(15, mkU32( dst & ~3 ));
16628            DIP("blx 0x%x (switch to ARM mode)\n", dst & ~3);
16629         }
16630         dres.whatNext    = Dis_StopHere;
16631         dres.jk_StopHere = Ijk_Call;
16632         goto decode_success;
16633      }
16634   }
16635
16636   /* ---------------- {LD,ST}M{IA,DB} ---------------- */
16637   if (0x3a2 == INSN0(15,6) // {LD,ST}MIA
16638       || 0x3a4 == INSN0(15,6)) { // {LD,ST}MDB
16639      UInt bW      = INSN0(5,5); /* writeback Rn ? */
16640      UInt bL      = INSN0(4,4);
16641      UInt rN      = INSN0(3,0);
16642      UInt bP      = INSN1(15,15); /* reglist entry for r15 */
16643      UInt bM      = INSN1(14,14); /* reglist entry for r14 */
16644      UInt rLmost  = INSN1(12,0);  /* reglist entry for r0 .. 12 */
16645      UInt rL13    = INSN1(13,13); /* must be zero */
16646      UInt regList = 0;
16647      Bool valid   = True;
16648
16649      UInt bINC    = 1;
16650      UInt bBEFORE = 0;
16651      if (INSN0(15,6) == 0x3a4) {
16652         bINC    = 0;
16653         bBEFORE = 1;
16654      }
16655
16656      /* detect statically invalid cases, and construct the final
16657         reglist */
16658      if (rL13 == 1)
16659         valid = False;
16660
16661      if (bL == 1) {
16662         regList = (bP << 15) | (bM << 14) | rLmost;
16663         if (rN == 15)                       valid = False;
16664         if (popcount32(regList) < 2)        valid = False;
16665         if (bP == 1 && bM == 1)             valid = False;
16666         if (bW == 1 && (regList & (1<<rN))) valid = False;
16667      } else {
16668         regList = (bM << 14) | rLmost;
16669         if (bP == 1)                        valid = False;
16670         if (rN == 15)                       valid = False;
16671         if (popcount32(regList) < 2)        valid = False;
16672         if (bW == 1 && (regList & (1<<rN))) valid = False;
16673      }
16674
16675      if (valid) {
16676         if (bL == 1 && bP == 1) {
16677            // We'll be writing the PC.  Hence:
16678            /* Only allowed outside or last-in IT block; SIGILL if not so. */
16679            gen_SIGILL_T_if_in_but_NLI_ITBlock(old_itstate, new_itstate);
16680         }
16681
16682         /* Go uncond: */
16683         mk_skip_over_T32_if_cond_is_false(condT);
16684         condT = IRTemp_INVALID;
16685         // now uncond
16686
16687         /* Generate the IR.  This might generate a write to R15. */
16688         mk_ldm_stm(False/*!arm*/, rN, bINC, bBEFORE, bW, bL, regList);
16689
16690         if (bL == 1 && (regList & (1<<15))) {
16691            // If we wrote to R15, we have an interworking return to
16692            // deal with.
16693            llPutIReg(15, llGetIReg(15));
16694            dres.jk_StopHere = Ijk_Ret;
16695            dres.whatNext    = Dis_StopHere;
16696         }
16697
16698         DIP("%sm%c%c r%u%s, {0x%04x}\n",
16699              bL == 1 ? "ld" : "st", bINC ? 'i' : 'd', bBEFORE ? 'b' : 'a',
16700              rN, bW ? "!" : "", regList);
16701
16702         goto decode_success;
16703      }
16704   }
16705
16706   /* -------------- (T3) ADD{S}.W Rd, Rn, #constT -------------- */
16707   if (INSN0(15,11) == BITS5(1,1,1,1,0)
16708       && INSN0(9,5) == BITS5(0,1,0,0,0)
16709       && INSN1(15,15) == 0) {
16710      UInt bS = INSN0(4,4);
16711      UInt rN = INSN0(3,0);
16712      UInt rD = INSN1(11,8);
16713      Bool valid = !isBadRegT(rN) && !isBadRegT(rD);
16714      /* but allow "add.w reg, sp, #constT" for reg != PC */
16715      if (!valid && rD <= 14 && rN == 13)
16716         valid = True;
16717      if (valid) {
16718         IRTemp argL  = newTemp(Ity_I32);
16719         IRTemp argR  = newTemp(Ity_I32);
16720         IRTemp res   = newTemp(Ity_I32);
16721         UInt   imm32 = thumbExpandImm_from_I0_I1(NULL, insn0, insn1);
16722         assign(argL, getIRegT(rN));
16723         assign(argR, mkU32(imm32));
16724         assign(res,  binop(Iop_Add32, mkexpr(argL), mkexpr(argR)));
16725         putIRegT(rD, mkexpr(res), condT);
16726         if (bS == 1)
16727            setFlags_D1_D2( ARMG_CC_OP_ADD, argL, argR, condT );
16728         DIP("add%s.w r%u, r%u, #%u\n",
16729             bS == 1 ? "s" : "", rD, rN, imm32);
16730         goto decode_success;
16731      }
16732   }
16733
16734   /* ---------------- (T4) ADDW Rd, Rn, #uimm12 -------------- */
16735   if (INSN0(15,11) == BITS5(1,1,1,1,0)
16736       && INSN0(9,4) == BITS6(1,0,0,0,0,0)
16737       && INSN1(15,15) == 0) {
16738      UInt rN = INSN0(3,0);
16739      UInt rD = INSN1(11,8);
16740      Bool valid = !isBadRegT(rN) && !isBadRegT(rD);
16741      /* but allow "addw reg, sp, #uimm12" for reg != PC */
16742      if (!valid && rD <= 14 && rN == 13)
16743         valid = True;
16744      if (valid) {
16745         IRTemp argL = newTemp(Ity_I32);
16746         IRTemp argR = newTemp(Ity_I32);
16747         IRTemp res  = newTemp(Ity_I32);
16748         UInt imm12  = (INSN0(10,10) << 11) | (INSN1(14,12) << 8) | INSN1(7,0);
16749         assign(argL, getIRegT(rN));
16750         assign(argR, mkU32(imm12));
16751         assign(res,  binop(Iop_Add32, mkexpr(argL), mkexpr(argR)));
16752         putIRegT(rD, mkexpr(res), condT);
16753         DIP("addw r%u, r%u, #%u\n", rD, rN, imm12);
16754         goto decode_success;
16755      }
16756   }
16757
16758   /* ---------------- (T2) CMP.W Rn, #constT ---------------- */
16759   /* ---------------- (T2) CMN.W Rn, #constT ---------------- */
16760   if (INSN0(15,11) == BITS5(1,1,1,1,0)
16761       && (   INSN0(9,4) == BITS6(0,1,1,0,1,1)  // CMP
16762           || INSN0(9,4) == BITS6(0,1,0,0,0,1)) // CMN
16763       && INSN1(15,15) == 0
16764       && INSN1(11,8) == BITS4(1,1,1,1)) {
16765      UInt rN = INSN0(3,0);
16766      if (rN != 15) {
16767         IRTemp argL  = newTemp(Ity_I32);
16768         IRTemp argR  = newTemp(Ity_I32);
16769         Bool   isCMN = INSN0(9,4) == BITS6(0,1,0,0,0,1);
16770         UInt   imm32 = thumbExpandImm_from_I0_I1(NULL, insn0, insn1);
16771         assign(argL, getIRegT(rN));
16772         assign(argR, mkU32(imm32));
16773         setFlags_D1_D2( isCMN ? ARMG_CC_OP_ADD : ARMG_CC_OP_SUB,
16774                         argL, argR, condT );
16775         DIP("%s.w r%u, #%u\n", isCMN ? "cmn" : "cmp", rN, imm32);
16776         goto decode_success;
16777      }
16778   }
16779
16780   /* -------------- (T1) TST.W Rn, #constT -------------- */
16781   /* -------------- (T1) TEQ.W Rn, #constT -------------- */
16782   if (INSN0(15,11) == BITS5(1,1,1,1,0)
16783       && (   INSN0(9,4) == BITS6(0,0,0,0,0,1)  // TST
16784           || INSN0(9,4) == BITS6(0,0,1,0,0,1)) // TEQ
16785       && INSN1(15,15) == 0
16786       && INSN1(11,8) == BITS4(1,1,1,1)) {
16787      UInt rN = INSN0(3,0);
16788      if (!isBadRegT(rN)) { // yes, really, it's inconsistent with CMP.W
16789         Bool  isTST  = INSN0(9,4) == BITS6(0,0,0,0,0,1);
16790         IRTemp argL  = newTemp(Ity_I32);
16791         IRTemp argR  = newTemp(Ity_I32);
16792         IRTemp res   = newTemp(Ity_I32);
16793         IRTemp oldV  = newTemp(Ity_I32);
16794         IRTemp oldC  = newTemp(Ity_I32);
16795         Bool   updC  = False;
16796         UInt   imm32 = thumbExpandImm_from_I0_I1(&updC, insn0, insn1);
16797         assign(argL, getIRegT(rN));
16798         assign(argR, mkU32(imm32));
16799         assign(res,  binop(isTST ? Iop_And32 : Iop_Xor32,
16800                            mkexpr(argL), mkexpr(argR)));
16801         assign( oldV, mk_armg_calculate_flag_v() );
16802         assign( oldC, updC
16803                       ? mkU32((imm32 >> 31) & 1)
16804                       : mk_armg_calculate_flag_c() );
16805         setFlags_D1_D2_ND( ARMG_CC_OP_LOGIC, res, oldC, oldV, condT );
16806         DIP("%s.w r%u, #%u\n", isTST ? "tst" : "teq", rN, imm32);
16807         goto decode_success;
16808      }
16809   }
16810
16811   /* -------------- (T3) SUB{S}.W Rd, Rn, #constT -------------- */
16812   /* -------------- (T3) RSB{S}.W Rd, Rn, #constT -------------- */
16813   if (INSN0(15,11) == BITS5(1,1,1,1,0)
16814       && (INSN0(9,5) == BITS5(0,1,1,0,1) // SUB
16815           || INSN0(9,5) == BITS5(0,1,1,1,0)) // RSB
16816       && INSN1(15,15) == 0) {
16817      Bool isRSB = INSN0(9,5) == BITS5(0,1,1,1,0);
16818      UInt bS    = INSN0(4,4);
16819      UInt rN    = INSN0(3,0);
16820      UInt rD    = INSN1(11,8);
16821      Bool valid = !isBadRegT(rN) && !isBadRegT(rD);
16822      /* but allow "sub{s}.w reg, sp, #constT
16823         this is (T2) of "SUB (SP minus immediate)" */
16824      if (!valid && !isRSB && rN == 13 && rD != 15)
16825         valid = True;
16826      if (valid) {
16827         IRTemp argL  = newTemp(Ity_I32);
16828         IRTemp argR  = newTemp(Ity_I32);
16829         IRTemp res   = newTemp(Ity_I32);
16830         UInt   imm32 = thumbExpandImm_from_I0_I1(NULL, insn0, insn1);
16831         assign(argL, getIRegT(rN));
16832         assign(argR, mkU32(imm32));
16833         assign(res,  isRSB
16834                      ? binop(Iop_Sub32, mkexpr(argR), mkexpr(argL))
16835                      : binop(Iop_Sub32, mkexpr(argL), mkexpr(argR)));
16836         putIRegT(rD, mkexpr(res), condT);
16837         if (bS == 1) {
16838            if (isRSB)
16839               setFlags_D1_D2( ARMG_CC_OP_SUB, argR, argL, condT );
16840            else
16841               setFlags_D1_D2( ARMG_CC_OP_SUB, argL, argR, condT );
16842         }
16843         DIP("%s%s.w r%u, r%u, #%u\n",
16844             isRSB ? "rsb" : "sub", bS == 1 ? "s" : "", rD, rN, imm32);
16845         goto decode_success;
16846      }
16847   }
16848
16849   /* -------------- (T4) SUBW Rd, Rn, #uimm12 ------------------- */
16850   if (INSN0(15,11) == BITS5(1,1,1,1,0)
16851       && INSN0(9,4) == BITS6(1,0,1,0,1,0)
16852       && INSN1(15,15) == 0) {
16853      UInt rN = INSN0(3,0);
16854      UInt rD = INSN1(11,8);
16855      Bool valid = !isBadRegT(rN) && !isBadRegT(rD);
16856      /* but allow "subw sp, sp, #uimm12" */
16857      if (!valid && rD == 13 && rN == 13)
16858         valid = True;
16859      if (valid) {
16860         IRTemp argL  = newTemp(Ity_I32);
16861         IRTemp argR  = newTemp(Ity_I32);
16862         IRTemp res   = newTemp(Ity_I32);
16863         UInt imm12   = (INSN0(10,10) << 11) | (INSN1(14,12) << 8) | INSN1(7,0);
16864         assign(argL, getIRegT(rN));
16865         assign(argR, mkU32(imm12));
16866         assign(res,  binop(Iop_Sub32, mkexpr(argL), mkexpr(argR)));
16867         putIRegT(rD, mkexpr(res), condT);
16868         DIP("subw r%u, r%u, #%u\n", rD, rN, imm12);
16869         goto decode_success;
16870      }
16871   }
16872
16873   /* -------------- (T1) ADC{S}.W Rd, Rn, #constT -------------- */
16874   /* -------------- (T1) SBC{S}.W Rd, Rn, #constT -------------- */
16875   if (INSN0(15,11) == BITS5(1,1,1,1,0)
16876       && (   INSN0(9,5) == BITS5(0,1,0,1,0)  // ADC
16877           || INSN0(9,5) == BITS5(0,1,0,1,1)) // SBC
16878       && INSN1(15,15) == 0) {
16879      /* ADC:  Rd = Rn + constT + oldC */
16880      /* SBC:  Rd = Rn - constT - (oldC ^ 1) */
16881      UInt bS    = INSN0(4,4);
16882      UInt rN    = INSN0(3,0);
16883      UInt rD    = INSN1(11,8);
16884      if (!isBadRegT(rN) && !isBadRegT(rD)) {
16885         IRTemp argL  = newTemp(Ity_I32);
16886         IRTemp argR  = newTemp(Ity_I32);
16887         IRTemp res   = newTemp(Ity_I32);
16888         IRTemp oldC  = newTemp(Ity_I32);
16889         UInt   imm32 = thumbExpandImm_from_I0_I1(NULL, insn0, insn1);
16890         assign(argL, getIRegT(rN));
16891         assign(argR, mkU32(imm32));
16892         assign(oldC, mk_armg_calculate_flag_c() );
16893         HChar* nm  = "???";
16894         switch (INSN0(9,5)) {
16895            case BITS5(0,1,0,1,0): // ADC
16896               nm = "adc";
16897               assign(res,
16898                      binop(Iop_Add32,
16899                            binop(Iop_Add32, mkexpr(argL), mkexpr(argR)),
16900                            mkexpr(oldC) ));
16901               putIRegT(rD, mkexpr(res), condT);
16902               if (bS)
16903                  setFlags_D1_D2_ND( ARMG_CC_OP_ADC,
16904                                     argL, argR, oldC, condT );
16905               break;
16906            case BITS5(0,1,0,1,1): // SBC
16907               nm = "sbc";
16908               assign(res,
16909                      binop(Iop_Sub32,
16910                            binop(Iop_Sub32, mkexpr(argL), mkexpr(argR)),
16911                            binop(Iop_Xor32, mkexpr(oldC), mkU32(1)) ));
16912               putIRegT(rD, mkexpr(res), condT);
16913               if (bS)
16914                  setFlags_D1_D2_ND( ARMG_CC_OP_SBB,
16915                                     argL, argR, oldC, condT );
16916               break;
16917            default:
16918              vassert(0);
16919         }
16920         DIP("%s%s.w r%u, r%u, #%u\n",
16921             nm, bS == 1 ? "s" : "", rD, rN, imm32);
16922         goto decode_success;
16923      }
16924   }
16925
16926   /* -------------- (T1) ORR{S}.W Rd, Rn, #constT -------------- */
16927   /* -------------- (T1) AND{S}.W Rd, Rn, #constT -------------- */
16928   /* -------------- (T1) BIC{S}.W Rd, Rn, #constT -------------- */
16929   /* -------------- (T1) EOR{S}.W Rd, Rn, #constT -------------- */
16930   if (INSN0(15,11) == BITS5(1,1,1,1,0)
16931       && (   INSN0(9,5) == BITS5(0,0,0,1,0)  // ORR
16932           || INSN0(9,5) == BITS5(0,0,0,0,0)  // AND
16933           || INSN0(9,5) == BITS5(0,0,0,0,1)  // BIC
16934           || INSN0(9,5) == BITS5(0,0,1,0,0)  // EOR
16935           || INSN0(9,5) == BITS5(0,0,0,1,1)) // ORN
16936       && INSN1(15,15) == 0) {
16937      UInt bS = INSN0(4,4);
16938      UInt rN = INSN0(3,0);
16939      UInt rD = INSN1(11,8);
16940      if (!isBadRegT(rN) && !isBadRegT(rD)) {
16941         Bool   notArgR = False;
16942         IROp   op      = Iop_INVALID;
16943         HChar* nm      = "???";
16944         switch (INSN0(9,5)) {
16945            case BITS5(0,0,0,1,0): op = Iop_Or32;  nm = "orr"; break;
16946            case BITS5(0,0,0,0,0): op = Iop_And32; nm = "and"; break;
16947            case BITS5(0,0,0,0,1): op = Iop_And32; nm = "bic";
16948                                   notArgR = True; break;
16949            case BITS5(0,0,1,0,0): op = Iop_Xor32; nm = "eor"; break;
16950            case BITS5(0,0,0,1,1): op = Iop_Or32;  nm = "orn";
16951                                   notArgR = True; break;
16952            default: vassert(0);
16953         }
16954         IRTemp argL  = newTemp(Ity_I32);
16955         IRTemp argR  = newTemp(Ity_I32);
16956         IRTemp res   = newTemp(Ity_I32);
16957         Bool   updC  = False;
16958         UInt   imm32 = thumbExpandImm_from_I0_I1(&updC, insn0, insn1);
16959         assign(argL, getIRegT(rN));
16960         assign(argR, mkU32(notArgR ? ~imm32 : imm32));
16961         assign(res,  binop(op, mkexpr(argL), mkexpr(argR)));
16962         putIRegT(rD, mkexpr(res), condT);
16963         if (bS) {
16964            IRTemp oldV = newTemp(Ity_I32);
16965            IRTemp oldC = newTemp(Ity_I32);
16966            assign( oldV, mk_armg_calculate_flag_v() );
16967            assign( oldC, updC
16968                          ? mkU32((imm32 >> 31) & 1)
16969                          : mk_armg_calculate_flag_c() );
16970            setFlags_D1_D2_ND( ARMG_CC_OP_LOGIC, res, oldC, oldV,
16971                               condT );
16972         }
16973         DIP("%s%s.w r%u, r%u, #%u\n",
16974             nm, bS == 1 ? "s" : "", rD, rN, imm32);
16975         goto decode_success;
16976      }
16977   }
16978
16979   /* ---------- (T3) ADD{S}.W Rd, Rn, Rm, {shift} ---------- */
16980   /* ---------- (T3) SUB{S}.W Rd, Rn, Rm, {shift} ---------- */
16981   /* ---------- (T3) RSB{S}.W Rd, Rn, Rm, {shift} ---------- */
16982   if (INSN0(15,9) == BITS7(1,1,1,0,1,0,1)
16983       && (   INSN0(8,5) == BITS4(1,0,0,0)  // add subopc
16984           || INSN0(8,5) == BITS4(1,1,0,1)  // sub subopc
16985           || INSN0(8,5) == BITS4(1,1,1,0)) // rsb subopc
16986       && INSN1(15,15) == 0) {
16987      UInt rN   = INSN0(3,0);
16988      UInt rD   = INSN1(11,8);
16989      UInt rM   = INSN1(3,0);
16990      UInt bS   = INSN0(4,4);
16991      UInt imm5 = (INSN1(14,12) << 2) | INSN1(7,6);
16992      UInt how  = INSN1(5,4);
16993
16994      Bool valid = !isBadRegT(rD) && !isBadRegT(rN) && !isBadRegT(rM);
16995      /* but allow "add.w reg, sp, reg, lsl #N for N=0,1,2 or 3
16996         (T3) "ADD (SP plus register) */
16997      if (!valid && INSN0(8,5) == BITS4(1,0,0,0) // add
16998          && rD != 15 && rN == 13 && imm5 <= 3 && how == 0) {
16999         valid = True;
17000      }
17001      /* also allow "sub.w reg, sp, reg   w/ no shift
17002         (T1) "SUB (SP minus register) */
17003      if (!valid && INSN0(8,5) == BITS4(1,1,0,1) // sub
17004          && rD != 15 && rN == 13 && imm5 == 0 && how == 0) {
17005         valid = True;
17006      }
17007      if (valid) {
17008         Bool   swap = False;
17009         IROp   op   = Iop_INVALID;
17010         HChar* nm   = "???";
17011         switch (INSN0(8,5)) {
17012            case BITS4(1,0,0,0): op = Iop_Add32; nm = "add"; break;
17013            case BITS4(1,1,0,1): op = Iop_Sub32; nm = "sub"; break;
17014            case BITS4(1,1,1,0): op = Iop_Sub32; nm = "rsb";
17015                                 swap = True; break;
17016            default: vassert(0);
17017         }
17018
17019         IRTemp argL = newTemp(Ity_I32);
17020         assign(argL, getIRegT(rN));
17021
17022         IRTemp rMt = newTemp(Ity_I32);
17023         assign(rMt, getIRegT(rM));
17024
17025         IRTemp argR = newTemp(Ity_I32);
17026         compute_result_and_C_after_shift_by_imm5(
17027            dis_buf, &argR, NULL, rMt, how, imm5, rM
17028         );
17029
17030         IRTemp res = newTemp(Ity_I32);
17031         assign(res, swap
17032                     ? binop(op, mkexpr(argR), mkexpr(argL))
17033                     : binop(op, mkexpr(argL), mkexpr(argR)));
17034
17035         putIRegT(rD, mkexpr(res), condT);
17036         if (bS) {
17037            switch (op) {
17038               case Iop_Add32:
17039                  setFlags_D1_D2( ARMG_CC_OP_ADD, argL, argR, condT );
17040                  break;
17041               case Iop_Sub32:
17042                  if (swap)
17043                     setFlags_D1_D2( ARMG_CC_OP_SUB, argR, argL, condT );
17044                  else
17045                     setFlags_D1_D2( ARMG_CC_OP_SUB, argL, argR, condT );
17046                  break;
17047               default:
17048                  vassert(0);
17049            }
17050         }
17051
17052         DIP("%s%s.w r%u, r%u, %s\n",
17053             nm, bS ? "s" : "", rD, rN, dis_buf);
17054         goto decode_success;
17055      }
17056   }
17057
17058   /* ---------- (T3) ADC{S}.W Rd, Rn, Rm, {shift} ---------- */
17059   /* ---------- (T2) SBC{S}.W Rd, Rn, Rm, {shift} ---------- */
17060   if (INSN0(15,9) == BITS7(1,1,1,0,1,0,1)
17061       && (   INSN0(8,5) == BITS4(1,0,1,0)   // adc subopc
17062           || INSN0(8,5) == BITS4(1,0,1,1))  // sbc subopc
17063       && INSN1(15,15) == 0) {
17064      /* ADC:  Rd = Rn + shifter_operand + oldC */
17065      /* SBC:  Rd = Rn - shifter_operand - (oldC ^ 1) */
17066      UInt rN = INSN0(3,0);
17067      UInt rD = INSN1(11,8);
17068      UInt rM = INSN1(3,0);
17069      if (!isBadRegT(rD) && !isBadRegT(rN) && !isBadRegT(rM)) {
17070         UInt bS   = INSN0(4,4);
17071         UInt imm5 = (INSN1(14,12) << 2) | INSN1(7,6);
17072         UInt how  = INSN1(5,4);
17073
17074         IRTemp argL = newTemp(Ity_I32);
17075         assign(argL, getIRegT(rN));
17076
17077         IRTemp rMt = newTemp(Ity_I32);
17078         assign(rMt, getIRegT(rM));
17079
17080         IRTemp oldC = newTemp(Ity_I32);
17081         assign(oldC, mk_armg_calculate_flag_c());
17082
17083         IRTemp argR = newTemp(Ity_I32);
17084         compute_result_and_C_after_shift_by_imm5(
17085            dis_buf, &argR, NULL, rMt, how, imm5, rM
17086         );
17087
17088         HChar* nm  = "???";
17089         IRTemp res = newTemp(Ity_I32);
17090         switch (INSN0(8,5)) {
17091            case BITS4(1,0,1,0): // ADC
17092               nm = "adc";
17093               assign(res,
17094                      binop(Iop_Add32,
17095                            binop(Iop_Add32, mkexpr(argL), mkexpr(argR)),
17096                            mkexpr(oldC) ));
17097               putIRegT(rD, mkexpr(res), condT);
17098               if (bS)
17099                  setFlags_D1_D2_ND( ARMG_CC_OP_ADC,
17100                                     argL, argR, oldC, condT );
17101               break;
17102            case BITS4(1,0,1,1): // SBC
17103               nm = "sbc";
17104               assign(res,
17105                      binop(Iop_Sub32,
17106                            binop(Iop_Sub32, mkexpr(argL), mkexpr(argR)),
17107                            binop(Iop_Xor32, mkexpr(oldC), mkU32(1)) ));
17108               putIRegT(rD, mkexpr(res), condT);
17109               if (bS)
17110                  setFlags_D1_D2_ND( ARMG_CC_OP_SBB,
17111                                     argL, argR, oldC, condT );
17112               break;
17113            default:
17114               vassert(0);
17115         }
17116
17117         DIP("%s%s.w r%u, r%u, %s\n",
17118             nm, bS ? "s" : "", rD, rN, dis_buf);
17119         goto decode_success;
17120      }
17121   }
17122
17123   /* ---------- (T3) AND{S}.W Rd, Rn, Rm, {shift} ---------- */
17124   /* ---------- (T3) ORR{S}.W Rd, Rn, Rm, {shift} ---------- */
17125   /* ---------- (T3) EOR{S}.W Rd, Rn, Rm, {shift} ---------- */
17126   /* ---------- (T3) BIC{S}.W Rd, Rn, Rm, {shift} ---------- */
17127   /* ---------- (T1) ORN{S}.W Rd, Rn, Rm, {shift} ---------- */
17128   if (INSN0(15,9) == BITS7(1,1,1,0,1,0,1)
17129       && (   INSN0(8,5) == BITS4(0,0,0,0)  // and subopc
17130           || INSN0(8,5) == BITS4(0,0,1,0)  // orr subopc
17131           || INSN0(8,5) == BITS4(0,1,0,0)  // eor subopc
17132           || INSN0(8,5) == BITS4(0,0,0,1)  // bic subopc
17133           || INSN0(8,5) == BITS4(0,0,1,1)) // orn subopc
17134       && INSN1(15,15) == 0) {
17135      UInt rN = INSN0(3,0);
17136      UInt rD = INSN1(11,8);
17137      UInt rM = INSN1(3,0);
17138      if (!isBadRegT(rD) && !isBadRegT(rN) && !isBadRegT(rM)) {
17139         Bool notArgR = False;
17140         IROp op      = Iop_INVALID;
17141         HChar* nm  = "???";
17142         switch (INSN0(8,5)) {
17143            case BITS4(0,0,0,0): op = Iop_And32; nm = "and"; break;
17144            case BITS4(0,0,1,0): op = Iop_Or32;  nm = "orr"; break;
17145            case BITS4(0,1,0,0): op = Iop_Xor32; nm = "eor"; break;
17146            case BITS4(0,0,0,1): op = Iop_And32; nm = "bic";
17147                                 notArgR = True; break;
17148            case BITS4(0,0,1,1): op = Iop_Or32; nm = "orn";
17149                                 notArgR = True; break;
17150            default: vassert(0);
17151         }
17152         UInt bS   = INSN0(4,4);
17153         UInt imm5 = (INSN1(14,12) << 2) | INSN1(7,6);
17154         UInt how  = INSN1(5,4);
17155
17156         IRTemp rNt = newTemp(Ity_I32);
17157         assign(rNt, getIRegT(rN));
17158
17159         IRTemp rMt = newTemp(Ity_I32);
17160         assign(rMt, getIRegT(rM));
17161
17162         IRTemp argR = newTemp(Ity_I32);
17163         IRTemp oldC = bS ? newTemp(Ity_I32) : IRTemp_INVALID;
17164
17165         compute_result_and_C_after_shift_by_imm5(
17166            dis_buf, &argR, bS ? &oldC : NULL, rMt, how, imm5, rM
17167         );
17168
17169         IRTemp res = newTemp(Ity_I32);
17170         if (notArgR) {
17171            vassert(op == Iop_And32 || op == Iop_Or32);
17172            assign(res, binop(op, mkexpr(rNt),
17173                                  unop(Iop_Not32, mkexpr(argR))));
17174         } else {
17175            assign(res, binop(op, mkexpr(rNt), mkexpr(argR)));
17176         }
17177
17178         putIRegT(rD, mkexpr(res), condT);
17179         if (bS) {
17180            IRTemp oldV = newTemp(Ity_I32);
17181            assign( oldV, mk_armg_calculate_flag_v() );
17182            setFlags_D1_D2_ND( ARMG_CC_OP_LOGIC, res, oldC, oldV,
17183                               condT );
17184         }
17185
17186         DIP("%s%s.w r%u, r%u, %s\n",
17187             nm, bS ? "s" : "", rD, rN, dis_buf);
17188         goto decode_success;
17189      }
17190   }
17191
17192   /* -------------- (T?) LSL{S}.W Rd, Rn, Rm -------------- */
17193   /* -------------- (T?) LSR{S}.W Rd, Rn, Rm -------------- */
17194   /* -------------- (T?) ASR{S}.W Rd, Rn, Rm -------------- */
17195   /* -------------- (T?) ROR{S}.W Rd, Rn, Rm -------------- */
17196   if (INSN0(15,7) == BITS9(1,1,1,1,1,0,1,0,0)
17197       && INSN1(15,12) == BITS4(1,1,1,1)
17198       && INSN1(7,4) == BITS4(0,0,0,0)) {
17199      UInt how = INSN0(6,5); // standard encoding
17200      UInt rN  = INSN0(3,0);
17201      UInt rD  = INSN1(11,8);
17202      UInt rM  = INSN1(3,0);
17203      UInt bS  = INSN0(4,4);
17204      Bool valid = !isBadRegT(rN) && !isBadRegT(rM) && !isBadRegT(rD);
17205      if (valid) {
17206         IRTemp rNt    = newTemp(Ity_I32);
17207         IRTemp rMt    = newTemp(Ity_I32);
17208         IRTemp res    = newTemp(Ity_I32);
17209         IRTemp oldC   = bS ? newTemp(Ity_I32) : IRTemp_INVALID;
17210         IRTemp oldV   = bS ? newTemp(Ity_I32) : IRTemp_INVALID;
17211         HChar* nms[4] = { "lsl", "lsr", "asr", "ror" };
17212         HChar* nm     = nms[how];
17213         assign(rNt, getIRegT(rN));
17214         assign(rMt, getIRegT(rM));
17215         compute_result_and_C_after_shift_by_reg(
17216            dis_buf, &res, bS ? &oldC : NULL,
17217            rNt, how, rMt, rN, rM
17218         );
17219         if (bS)
17220            assign(oldV, mk_armg_calculate_flag_v());
17221         putIRegT(rD, mkexpr(res), condT);
17222         if (bS) {
17223            setFlags_D1_D2_ND( ARMG_CC_OP_LOGIC, res, oldC, oldV,
17224                               condT );
17225         }
17226         DIP("%s%s.w r%u, r%u, r%u\n",
17227             nm, bS ? "s" : "", rD, rN, rM);
17228         goto decode_success;
17229      }
17230   }
17231
17232   /* ------------ (T?) MOV{S}.W Rd, Rn, {shift} ------------ */
17233   /* ------------ (T?) MVN{S}.W Rd, Rn, {shift} ------------ */
17234   if ((INSN0(15,0) & 0xFFCF) == 0xEA4F
17235       && INSN1(15,15) == 0) {
17236      UInt rD = INSN1(11,8);
17237      UInt rN = INSN1(3,0);
17238      if (!isBadRegT(rD) && !isBadRegT(rN)) {
17239         UInt bS    = INSN0(4,4);
17240         UInt isMVN = INSN0(5,5);
17241         UInt imm5  = (INSN1(14,12) << 2) | INSN1(7,6);
17242         UInt how   = INSN1(5,4);
17243
17244         IRTemp rNt = newTemp(Ity_I32);
17245         assign(rNt, getIRegT(rN));
17246
17247         IRTemp oldRn = newTemp(Ity_I32);
17248         IRTemp oldC  = bS ? newTemp(Ity_I32) : IRTemp_INVALID;
17249         compute_result_and_C_after_shift_by_imm5(
17250            dis_buf, &oldRn, bS ? &oldC : NULL, rNt, how, imm5, rN
17251         );
17252
17253         IRTemp res = newTemp(Ity_I32);
17254         assign(res, isMVN ? unop(Iop_Not32, mkexpr(oldRn))
17255                           : mkexpr(oldRn));
17256
17257         putIRegT(rD, mkexpr(res), condT);
17258         if (bS) {
17259            IRTemp oldV = newTemp(Ity_I32);
17260            assign( oldV, mk_armg_calculate_flag_v() );
17261            setFlags_D1_D2_ND( ARMG_CC_OP_LOGIC, res, oldC, oldV, condT);
17262         }
17263         DIP("%s%s.w r%u, %s\n",
17264             isMVN ? "mvn" : "mov", bS ? "s" : "", rD, dis_buf);
17265         goto decode_success;
17266      }
17267   }
17268
17269   /* -------------- (T?) TST.W Rn, Rm, {shift} -------------- */
17270   /* -------------- (T?) TEQ.W Rn, Rm, {shift} -------------- */
17271   if (INSN0(15,9) == BITS7(1,1,1,0,1,0,1)
17272       && (   INSN0(8,4) == BITS5(0,0,0,0,1)  // TST
17273           || INSN0(8,4) == BITS5(0,1,0,0,1)) // TEQ
17274       && INSN1(15,15) == 0
17275       && INSN1(11,8) == BITS4(1,1,1,1)) {
17276      UInt rN = INSN0(3,0);
17277      UInt rM = INSN1(3,0);
17278      if (!isBadRegT(rN) && !isBadRegT(rM)) {
17279         Bool isTST = INSN0(8,4) == BITS5(0,0,0,0,1);
17280
17281         UInt how  = INSN1(5,4);
17282         UInt imm5 = (INSN1(14,12) << 2) | INSN1(7,6);
17283
17284         IRTemp argL = newTemp(Ity_I32);
17285         assign(argL, getIRegT(rN));
17286
17287         IRTemp rMt = newTemp(Ity_I32);
17288         assign(rMt, getIRegT(rM));
17289
17290         IRTemp argR = newTemp(Ity_I32);
17291         IRTemp oldC = newTemp(Ity_I32);
17292         compute_result_and_C_after_shift_by_imm5(
17293            dis_buf, &argR, &oldC, rMt, how, imm5, rM
17294         );
17295
17296         IRTemp oldV = newTemp(Ity_I32);
17297         assign( oldV, mk_armg_calculate_flag_v() );
17298
17299         IRTemp res = newTemp(Ity_I32);
17300         assign(res, binop(isTST ? Iop_And32 : Iop_Xor32,
17301                           mkexpr(argL), mkexpr(argR)));
17302
17303         setFlags_D1_D2_ND( ARMG_CC_OP_LOGIC, res, oldC, oldV,
17304                            condT );
17305         DIP("%s.w r%u, %s\n", isTST ? "tst" : "teq", rN, dis_buf);
17306         goto decode_success;
17307      }
17308   }
17309
17310   /* -------------- (T3) CMP.W Rn, Rm, {shift} -------------- */
17311   /* -------------- (T2) CMN.W Rn, Rm, {shift} -------------- */
17312   if (INSN0(15,9) == BITS7(1,1,1,0,1,0,1)
17313       && (   INSN0(8,4) == BITS5(1,1,0,1,1)  // CMP
17314           || INSN0(8,4) == BITS5(1,0,0,0,1)) // CMN
17315       && INSN1(15,15) == 0
17316       && INSN1(11,8) == BITS4(1,1,1,1)) {
17317      UInt rN = INSN0(3,0);
17318      UInt rM = INSN1(3,0);
17319      if (!isBadRegT(rN) && !isBadRegT(rM)) {
17320         Bool isCMN = INSN0(8,4) == BITS5(1,0,0,0,1);
17321         UInt how   = INSN1(5,4);
17322         UInt imm5  = (INSN1(14,12) << 2) | INSN1(7,6);
17323
17324         IRTemp argL = newTemp(Ity_I32);
17325         assign(argL, getIRegT(rN));
17326
17327         IRTemp rMt = newTemp(Ity_I32);
17328         assign(rMt, getIRegT(rM));
17329
17330         IRTemp argR = newTemp(Ity_I32);
17331         compute_result_and_C_after_shift_by_imm5(
17332            dis_buf, &argR, NULL, rMt, how, imm5, rM
17333         );
17334
17335         setFlags_D1_D2( isCMN ? ARMG_CC_OP_ADD : ARMG_CC_OP_SUB,
17336                         argL, argR, condT );
17337
17338         DIP("%s.w r%u, %s\n", isCMN ? "cmn" : "cmp", rN, dis_buf);
17339         goto decode_success;
17340      }
17341   }
17342
17343   /* -------------- (T2) MOV{S}.W Rd, #constT -------------- */
17344   /* -------------- (T2) MVN{S}.W Rd, #constT -------------- */
17345   if (INSN0(15,11) == BITS5(1,1,1,1,0)
17346       && (   INSN0(9,5) == BITS5(0,0,0,1,0)  // MOV
17347           || INSN0(9,5) == BITS5(0,0,0,1,1)) // MVN
17348       && INSN0(3,0) == BITS4(1,1,1,1)
17349       && INSN1(15,15) == 0) {
17350      UInt rD = INSN1(11,8);
17351      if (!isBadRegT(rD)) {
17352         Bool   updC  = False;
17353         UInt   bS    = INSN0(4,4);
17354         Bool   isMVN = INSN0(5,5) == 1;
17355         UInt   imm32 = thumbExpandImm_from_I0_I1(&updC, insn0, insn1);
17356         IRTemp res   = newTemp(Ity_I32);
17357         assign(res, mkU32(isMVN ? ~imm32 : imm32));
17358         putIRegT(rD, mkexpr(res), condT);
17359         if (bS) {
17360            IRTemp oldV = newTemp(Ity_I32);
17361            IRTemp oldC = newTemp(Ity_I32);
17362            assign( oldV, mk_armg_calculate_flag_v() );
17363            assign( oldC, updC
17364                          ? mkU32((imm32 >> 31) & 1)
17365                          : mk_armg_calculate_flag_c() );
17366            setFlags_D1_D2_ND( ARMG_CC_OP_LOGIC, res, oldC, oldV,
17367                               condT );
17368         }
17369         DIP("%s%s.w r%u, #%u\n",
17370             isMVN ? "mvn" : "mov", bS ? "s" : "", rD, imm32);
17371         goto decode_success;
17372      }
17373   }
17374
17375   /* -------------- (T3) MOVW Rd, #imm16 -------------- */
17376   if (INSN0(15,11) == BITS5(1,1,1,1,0)
17377       && INSN0(9,4) == BITS6(1,0,0,1,0,0)
17378       && INSN1(15,15) == 0) {
17379      UInt rD = INSN1(11,8);
17380      if (!isBadRegT(rD)) {
17381         UInt imm16 = (INSN0(3,0) << 12) | (INSN0(10,10) << 11)
17382                      | (INSN1(14,12) << 8) | INSN1(7,0);
17383         putIRegT(rD, mkU32(imm16), condT);
17384         DIP("movw r%u, #%u\n", rD, imm16);
17385         goto decode_success;
17386      }
17387   }
17388
17389   /* ---------------- MOVT Rd, #imm16 ---------------- */
17390   if (INSN0(15,11) == BITS5(1,1,1,1,0)
17391       && INSN0(9,4) == BITS6(1,0,1,1,0,0)
17392       && INSN1(15,15) == 0) {
17393      UInt rD = INSN1(11,8);
17394      if (!isBadRegT(rD)) {
17395         UInt imm16 = (INSN0(3,0) << 12) | (INSN0(10,10) << 11)
17396                      | (INSN1(14,12) << 8) | INSN1(7,0);
17397         IRTemp res = newTemp(Ity_I32);
17398         assign(res,
17399                binop(Iop_Or32,
17400                      binop(Iop_And32, getIRegT(rD), mkU32(0xFFFF)),
17401                      mkU32(imm16 << 16)));
17402         putIRegT(rD, mkexpr(res), condT);
17403         DIP("movt r%u, #%u\n", rD, imm16);
17404         goto decode_success;
17405      }
17406   }
17407
17408   /* ---------------- LD/ST reg+/-#imm8 ---------------- */
17409   /* Loads and stores of the form:
17410         op  Rt, [Rn, #-imm8]      or
17411         op  Rt, [Rn], #+/-imm8    or
17412         op  Rt, [Rn, #+/-imm8]!
17413      where op is one of
17414         ldrb ldrh ldr  ldrsb ldrsh
17415         strb strh str
17416   */
17417   if (INSN0(15,9) == BITS7(1,1,1,1,1,0,0) && INSN1(11,11) == 1) {
17418      Bool   valid  = True;
17419      Bool   syned  = False;
17420      Bool   isST   = False;
17421      IRType ty     = Ity_I8;
17422      HChar* nm     = "???";
17423
17424      switch (INSN0(8,4)) {
17425         case BITS5(0,0,0,0,0):   // strb
17426            nm = "strb"; isST = True; break;
17427         case BITS5(0,0,0,0,1):   // ldrb
17428            nm = "ldrb"; break;
17429         case BITS5(1,0,0,0,1):   // ldrsb
17430            nm = "ldrsb"; syned = True; break;
17431         case BITS5(0,0,0,1,0):   // strh
17432            nm = "strh"; ty = Ity_I16; isST = True; break;
17433         case BITS5(0,0,0,1,1):   // ldrh
17434            nm = "ldrh"; ty = Ity_I16; break;
17435         case BITS5(1,0,0,1,1):   // ldrsh
17436            nm = "ldrsh"; ty = Ity_I16; syned = True; break;
17437         case BITS5(0,0,1,0,0):   // str
17438            nm = "str"; ty = Ity_I32; isST = True; break;
17439         case BITS5(0,0,1,0,1):
17440            nm = "ldr"; ty = Ity_I32; break;  // ldr
17441         default:
17442            valid = False; break;
17443      }
17444
17445      UInt rN      = INSN0(3,0);
17446      UInt rT      = INSN1(15,12);
17447      UInt bP      = INSN1(10,10);
17448      UInt bU      = INSN1(9,9);
17449      UInt bW      = INSN1(8,8);
17450      UInt imm8    = INSN1(7,0);
17451      Bool loadsPC = False;
17452
17453      if (valid) {
17454         if (bP == 1 && bU == 1 && bW == 0)
17455            valid = False;
17456         if (bP == 0 && bW == 0)
17457            valid = False;
17458         if (rN == 15)
17459            valid = False;
17460         if (bW == 1 && rN == rT)
17461            valid = False;
17462         if (ty == Ity_I8 || ty == Ity_I16) {
17463            if (isBadRegT(rT))
17464               valid = False;
17465         } else {
17466            /* ty == Ity_I32 */
17467            if (isST && rT == 15)
17468               valid = False;
17469            if (!isST && rT == 15)
17470               loadsPC = True;
17471         }
17472      }
17473
17474      if (valid) {
17475         // if it's a branch, it can't happen in the middle of an IT block
17476         if (loadsPC)
17477            gen_SIGILL_T_if_in_but_NLI_ITBlock(old_itstate, new_itstate);
17478         // go uncond
17479         mk_skip_over_T32_if_cond_is_false(condT);
17480         condT = IRTemp_INVALID;
17481         // now uncond
17482
17483         IRTemp preAddr = newTemp(Ity_I32);
17484         assign(preAddr, getIRegT(rN));
17485
17486         IRTemp postAddr = newTemp(Ity_I32);
17487         assign(postAddr, binop(bU == 1 ? Iop_Add32 : Iop_Sub32,
17488                                mkexpr(preAddr), mkU32(imm8)));
17489
17490         IRTemp transAddr = bP == 1 ? postAddr : preAddr;
17491
17492         if (isST) {
17493
17494             /* Store.  If necessary, update the base register before
17495                the store itself, so that the common idiom of "str rX,
17496                [sp, #-4]!" (store rX at sp-4, then do new sp = sp-4,
17497                a.k.a "push rX") doesn't cause Memcheck to complain
17498                that the access is below the stack pointer.  Also, not
17499                updating sp before the store confuses Valgrind's
17500                dynamic stack-extending logic.  So do it before the
17501                store.  Hence we need to snarf the store data before
17502                doing the basereg update. */
17503
17504            /* get hold of the data to be stored */
17505            IRTemp oldRt = newTemp(Ity_I32);
17506            assign(oldRt, getIRegT(rT));
17507
17508            /* Update Rn if necessary. */
17509            if (bW == 1) {
17510               vassert(rN != rT); // assured by validity check above
17511               putIRegT(rN, mkexpr(postAddr), IRTemp_INVALID);
17512            }
17513
17514            /* generate the transfer */
17515            switch (ty) {
17516               case Ity_I8:
17517                  storeLE(mkexpr(transAddr),
17518                                 unop(Iop_32to8, mkexpr(oldRt)));
17519                  break;
17520               case Ity_I16:
17521                  storeLE(mkexpr(transAddr),
17522                          unop(Iop_32to16, mkexpr(oldRt)));
17523                  break;
17524              case Ity_I32:
17525                  storeLE(mkexpr(transAddr), mkexpr(oldRt));
17526                  break;
17527              default:
17528                 vassert(0);
17529            }
17530
17531         } else {
17532
17533            /* Load. */
17534
17535            /* generate the transfer */
17536            IRTemp newRt = newTemp(Ity_I32);
17537            IROp   widen = Iop_INVALID;
17538            switch (ty) {
17539               case Ity_I8:
17540                  widen = syned ? Iop_8Sto32 : Iop_8Uto32; break;
17541               case Ity_I16:
17542                  widen = syned ? Iop_16Sto32 : Iop_16Uto32; break;
17543               case Ity_I32:
17544                  break;
17545               default:
17546                  vassert(0);
17547            }
17548            if (widen == Iop_INVALID) {
17549               assign(newRt, loadLE(ty, mkexpr(transAddr)));
17550            } else {
17551               assign(newRt, unop(widen, loadLE(ty, mkexpr(transAddr))));
17552            }
17553            if (loadsPC) {
17554               vassert(rT == 15);
17555               llPutIReg(rT, mkexpr(newRt));
17556            } else {
17557               putIRegT(rT, mkexpr(newRt), IRTemp_INVALID);
17558            }
17559
17560            /* Update Rn if necessary. */
17561            if (bW == 1) {
17562               vassert(rN != rT); // assured by validity check above
17563               putIRegT(rN, mkexpr(postAddr), IRTemp_INVALID);
17564            }
17565
17566            if (loadsPC) {
17567               /* Presumably this is an interworking branch. */
17568               vassert(rN != 15); // assured by validity check above
17569               llPutIReg(15, mkexpr(newRt));
17570               dres.jk_StopHere = Ijk_Boring;  /* or _Ret ? */
17571               dres.whatNext    = Dis_StopHere;
17572            }
17573         }
17574
17575         if (bP == 1 && bW == 0) {
17576            DIP("%s.w r%u, [r%u, #%c%u]\n",
17577                nm, rT, rN, bU ? '+' : '-', imm8);
17578         }
17579         else if (bP == 1 && bW == 1) {
17580            DIP("%s.w r%u, [r%u, #%c%u]!\n",
17581                nm, rT, rN, bU ? '+' : '-', imm8);
17582         }
17583         else {
17584            vassert(bP == 0 && bW == 1);
17585            DIP("%s.w r%u, [r%u], #%c%u\n",
17586                nm, rT, rN, bU ? '+' : '-', imm8);
17587         }
17588
17589         goto decode_success;
17590      }
17591   }
17592
17593   /* ------------- LD/ST reg+(reg<<imm2) ------------- */
17594   /* Loads and stores of the form:
17595         op  Rt, [Rn, Rm, LSL #imm8]
17596      where op is one of
17597         ldrb ldrh ldr  ldrsb ldrsh
17598         strb strh str
17599   */
17600   if (INSN0(15,9) == BITS7(1,1,1,1,1,0,0)
17601       && INSN1(11,6) == BITS6(0,0,0,0,0,0)) {
17602      Bool   valid  = True;
17603      Bool   syned  = False;
17604      Bool   isST   = False;
17605      IRType ty     = Ity_I8;
17606      HChar* nm     = "???";
17607
17608      switch (INSN0(8,4)) {
17609         case BITS5(0,0,0,0,0):   // strb
17610            nm = "strb"; isST = True; break;
17611         case BITS5(0,0,0,0,1):   // ldrb
17612            nm = "ldrb"; break;
17613         case BITS5(1,0,0,0,1):   // ldrsb
17614            nm = "ldrsb"; syned = True; break;
17615         case BITS5(0,0,0,1,0):   // strh
17616            nm = "strh"; ty = Ity_I16; isST = True; break;
17617         case BITS5(0,0,0,1,1):   // ldrh
17618            nm = "ldrh"; ty = Ity_I16; break;
17619         case BITS5(1,0,0,1,1):   // ldrsh
17620            nm = "ldrsh"; ty = Ity_I16; syned = True; break;
17621         case BITS5(0,0,1,0,0):   // str
17622            nm = "str"; ty = Ity_I32; isST = True; break;
17623         case BITS5(0,0,1,0,1):
17624            nm = "ldr"; ty = Ity_I32; break;  // ldr
17625         default:
17626            valid = False; break;
17627      }
17628
17629      UInt rN      = INSN0(3,0);
17630      UInt rM      = INSN1(3,0);
17631      UInt rT      = INSN1(15,12);
17632      UInt imm2    = INSN1(5,4);
17633      Bool loadsPC = False;
17634
17635      if (ty == Ity_I8 || ty == Ity_I16) {
17636         /* all 8- and 16-bit load and store cases have the
17637            same exclusion set. */
17638         if (rN == 15 || isBadRegT(rT) || isBadRegT(rM))
17639            valid = False;
17640      } else {
17641         vassert(ty == Ity_I32);
17642         if (rN == 15 || isBadRegT(rM))
17643            valid = False;
17644         if (isST && rT == 15)
17645            valid = False;
17646         /* If it is a load and rT is 15, that's only allowable if we
17647            not in an IT block, or are the last in it.  Need to insert
17648            a dynamic check for that. */
17649         if (!isST && rT == 15)
17650            loadsPC = True;
17651      }
17652
17653      if (valid) {
17654         // if it's a branch, it can't happen in the middle of an IT block
17655         if (loadsPC)
17656            gen_SIGILL_T_if_in_but_NLI_ITBlock(old_itstate, new_itstate);
17657         // go uncond
17658         mk_skip_over_T32_if_cond_is_false(condT);
17659         condT = IRTemp_INVALID;
17660         // now uncond
17661
17662         IRTemp transAddr = newTemp(Ity_I32);
17663         assign(transAddr,
17664                binop( Iop_Add32,
17665                       getIRegT(rN),
17666                       binop(Iop_Shl32, getIRegT(rM), mkU8(imm2)) ));
17667
17668         if (isST) {
17669            IRTemp oldRt = newTemp(Ity_I32);
17670            assign(oldRt, getIRegT(rT));
17671            switch (ty) {
17672               case Ity_I8:
17673                  storeLE(mkexpr(transAddr),
17674                                 unop(Iop_32to8, mkexpr(oldRt)));
17675                  break;
17676               case Ity_I16:
17677                  storeLE(mkexpr(transAddr),
17678                          unop(Iop_32to16, mkexpr(oldRt)));
17679                  break;
17680              case Ity_I32:
17681                  storeLE(mkexpr(transAddr), mkexpr(oldRt));
17682                  break;
17683              default:
17684                 vassert(0);
17685            }
17686         } else {
17687            IRTemp newRt = newTemp(Ity_I32);
17688            IROp   widen = Iop_INVALID;
17689            switch (ty) {
17690               case Ity_I8:
17691                  widen = syned ? Iop_8Sto32 : Iop_8Uto32; break;
17692               case Ity_I16:
17693                  widen = syned ? Iop_16Sto32 : Iop_16Uto32; break;
17694               case Ity_I32:
17695                  break;
17696               default:
17697                  vassert(0);
17698            }
17699            if (widen == Iop_INVALID) {
17700               assign(newRt, loadLE(ty, mkexpr(transAddr)));
17701            } else {
17702               assign(newRt, unop(widen, loadLE(ty, mkexpr(transAddr))));
17703            }
17704
17705            /* If we're loading the PC, putIRegT will assert.  So go
17706               direct via llPutIReg.  In all other cases use putIRegT
17707               as it is safer (although could simply use llPutIReg for
17708               _all_ cases here.) */
17709            if (loadsPC) {
17710               vassert(rT == 15);
17711               llPutIReg(rT, mkexpr(newRt));
17712            } else {
17713               putIRegT(rT, mkexpr(newRt), IRTemp_INVALID);
17714            }
17715
17716            if (loadsPC) {
17717               /* Presumably this is an interworking branch. */
17718               llPutIReg(15, mkexpr(newRt));
17719               dres.jk_StopHere = Ijk_Boring;  /* or _Ret ? */
17720               dres.whatNext    = Dis_StopHere;
17721            }
17722         }
17723
17724         DIP("%s.w r%u, [r%u, r%u, LSL #%u]\n",
17725             nm, rT, rN, rM, imm2);
17726
17727         goto decode_success;
17728      }
17729   }
17730
17731   /* --------------- LD/ST reg+imm12 --------------- */
17732   /* Loads and stores of the form:
17733         op  Rt, [Rn, +#imm12]
17734      where op is one of
17735         ldrb ldrh ldr  ldrsb ldrsh
17736         strb strh str
17737   */
17738   if (INSN0(15,9) == BITS7(1,1,1,1,1,0,0)) {
17739      Bool   valid  = True;
17740      Bool   syned  = False;
17741      Bool   isST   = False;
17742      IRType ty     = Ity_I8;
17743      HChar* nm     = "???";
17744
17745      switch (INSN0(8,4)) {
17746         case BITS5(0,1,0,0,0):   // strb
17747            nm = "strb"; isST = True; break;
17748         case BITS5(0,1,0,0,1):   // ldrb
17749            nm = "ldrb"; break;
17750         case BITS5(1,1,0,0,1):   // ldrsb
17751            nm = "ldrsb"; syned = True; break;
17752         case BITS5(0,1,0,1,0):   // strh
17753            nm = "strh"; ty = Ity_I16; isST = True; break;
17754         case BITS5(0,1,0,1,1):   // ldrh
17755            nm = "ldrh"; ty = Ity_I16; break;
17756         case BITS5(1,1,0,1,1):   // ldrsh
17757            nm = "ldrsh"; ty = Ity_I16; syned = True; break;
17758         case BITS5(0,1,1,0,0):   // str
17759            nm = "str"; ty = Ity_I32; isST = True; break;
17760         case BITS5(0,1,1,0,1):
17761            nm = "ldr"; ty = Ity_I32; break;  // ldr
17762         default:
17763            valid = False; break;
17764      }
17765
17766      UInt rN      = INSN0(3,0);
17767      UInt rT      = INSN1(15,12);
17768      UInt imm12   = INSN1(11,0);
17769      Bool loadsPC = False;
17770
17771      if (ty == Ity_I8 || ty == Ity_I16) {
17772         /* all 8- and 16-bit load and store cases have the
17773            same exclusion set. */
17774         if (rN == 15 || isBadRegT(rT))
17775            valid = False;
17776      } else {
17777         vassert(ty == Ity_I32);
17778         if (isST) {
17779            if (rN == 15 || rT == 15)
17780               valid = False;
17781         } else {
17782            /* For a 32-bit load, rT == 15 is only allowable if we not
17783               in an IT block, or are the last in it.  Need to insert
17784               a dynamic check for that.  Also, in this particular
17785               case, rN == 15 is allowable.  In this case however, the
17786               value obtained for rN is (apparently)
17787               "word-align(address of current insn + 4)". */
17788            if (rT == 15)
17789               loadsPC = True;
17790         }
17791      }
17792
17793      if (valid) {
17794         // if it's a branch, it can't happen in the middle of an IT block
17795         if (loadsPC)
17796            gen_SIGILL_T_if_in_but_NLI_ITBlock(old_itstate, new_itstate);
17797         // go uncond
17798         mk_skip_over_T32_if_cond_is_false(condT);
17799         condT = IRTemp_INVALID;
17800         // now uncond
17801
17802         IRTemp rNt = newTemp(Ity_I32);
17803         if (rN == 15) {
17804            vassert(ty == Ity_I32 && !isST);
17805            assign(rNt, binop(Iop_And32, getIRegT(rN), mkU32(~3)));
17806         } else {
17807            assign(rNt, getIRegT(rN));
17808         }
17809
17810         IRTemp transAddr = newTemp(Ity_I32);
17811         assign(transAddr,
17812                binop( Iop_Add32, mkexpr(rNt), mkU32(imm12) ));
17813
17814         if (isST) {
17815            IRTemp oldRt = newTemp(Ity_I32);
17816            assign(oldRt, getIRegT(rT));
17817            switch (ty) {
17818               case Ity_I8:
17819                  storeLE(mkexpr(transAddr),
17820                                 unop(Iop_32to8, mkexpr(oldRt)));
17821                  break;
17822               case Ity_I16:
17823                  storeLE(mkexpr(transAddr),
17824                          unop(Iop_32to16, mkexpr(oldRt)));
17825                  break;
17826              case Ity_I32:
17827                  storeLE(mkexpr(transAddr), mkexpr(oldRt));
17828                  break;
17829              default:
17830                 vassert(0);
17831            }
17832         } else {
17833            IRTemp newRt = newTemp(Ity_I32);
17834            IROp   widen = Iop_INVALID;
17835            switch (ty) {
17836               case Ity_I8:
17837                  widen = syned ? Iop_8Sto32 : Iop_8Uto32; break;
17838               case Ity_I16:
17839                  widen = syned ? Iop_16Sto32 : Iop_16Uto32; break;
17840               case Ity_I32:
17841                  break;
17842               default:
17843                  vassert(0);
17844            }
17845            if (widen == Iop_INVALID) {
17846               assign(newRt, loadLE(ty, mkexpr(transAddr)));
17847            } else {
17848               assign(newRt, unop(widen, loadLE(ty, mkexpr(transAddr))));
17849            }
17850            putIRegT(rT, mkexpr(newRt), IRTemp_INVALID);
17851
17852            if (loadsPC) {
17853               /* Presumably this is an interworking branch. */
17854               irsb->next = mkexpr(newRt);
17855               irsb->jumpkind = Ijk_Boring;  /* or _Ret ? */
17856               dres.whatNext  = Dis_StopHere;
17857            }
17858         }
17859
17860         DIP("%s.w r%u, [r%u, +#%u]\n", nm, rT, rN, imm12);
17861
17862         goto decode_success;
17863      }
17864   }
17865
17866   /* -------------- LDRD/STRD reg+/-#imm8 -------------- */
17867   /* Doubleword loads and stores of the form:
17868         ldrd/strd  Rt, Rt2, [Rn, #-imm8]      or
17869         ldrd/strd  Rt, Rt2, [Rn], #+/-imm8    or
17870         ldrd/strd  Rt, Rt2, [Rn, #+/-imm8]!
17871   */
17872   if (INSN0(15,9) == BITS7(1,1,1,0,1,0,0) && INSN0(6,6) == 1) {
17873      UInt bP   = INSN0(8,8);
17874      UInt bU   = INSN0(7,7);
17875      UInt bW   = INSN0(5,5);
17876      UInt bL   = INSN0(4,4);  // 1: load  0: store
17877      UInt rN   = INSN0(3,0);
17878      UInt rT   = INSN1(15,12);
17879      UInt rT2  = INSN1(11,8);
17880      UInt imm8 = INSN1(7,0);
17881
17882      Bool valid = True;
17883      if (bP == 0 && bW == 0)                 valid = False;
17884      if (bW == 1 && (rN == rT || rN == rT2)) valid = False;
17885      if (isBadRegT(rT) || isBadRegT(rT2))    valid = False;
17886      if (rN == 15)                           valid = False;
17887      if (bL == 1 && rT == rT2)               valid = False;
17888
17889      if (valid) {
17890         // go uncond
17891         mk_skip_over_T32_if_cond_is_false(condT);
17892         condT = IRTemp_INVALID;
17893         // now uncond
17894
17895         IRTemp preAddr = newTemp(Ity_I32);
17896         assign(preAddr, getIRegT(rN));
17897
17898         IRTemp postAddr = newTemp(Ity_I32);
17899         assign(postAddr, binop(bU == 1 ? Iop_Add32 : Iop_Sub32,
17900                                mkexpr(preAddr), mkU32(imm8 << 2)));
17901
17902         IRTemp transAddr = bP == 1 ? postAddr : preAddr;
17903
17904         if (bL == 0) {
17905            IRTemp oldRt  = newTemp(Ity_I32);
17906            IRTemp oldRt2 = newTemp(Ity_I32);
17907            assign(oldRt,  getIRegT(rT));
17908            assign(oldRt2, getIRegT(rT2));
17909            storeLE(mkexpr(transAddr),
17910                    mkexpr(oldRt));
17911            storeLE(binop(Iop_Add32, mkexpr(transAddr), mkU32(4)),
17912                    mkexpr(oldRt2));
17913         } else {
17914            IRTemp newRt  = newTemp(Ity_I32);
17915            IRTemp newRt2 = newTemp(Ity_I32);
17916            assign(newRt,
17917                   loadLE(Ity_I32,
17918                          mkexpr(transAddr)));
17919            assign(newRt2,
17920                   loadLE(Ity_I32,
17921                          binop(Iop_Add32, mkexpr(transAddr), mkU32(4))));
17922            putIRegT(rT,  mkexpr(newRt), IRTemp_INVALID);
17923            putIRegT(rT2, mkexpr(newRt2), IRTemp_INVALID);
17924         }
17925
17926         if (bW == 1) {
17927            putIRegT(rN, mkexpr(postAddr), IRTemp_INVALID);
17928         }
17929
17930         HChar* nm = bL ? "ldrd" : "strd";
17931
17932         if (bP == 1 && bW == 0) {
17933            DIP("%s.w r%u, r%u, [r%u, #%c%u]\n",
17934                nm, rT, rT2, rN, bU ? '+' : '-', imm8 << 2);
17935         }
17936         else if (bP == 1 && bW == 1) {
17937            DIP("%s.w r%u, r%u, [r%u, #%c%u]!\n",
17938                nm, rT, rT2, rN, bU ? '+' : '-', imm8 << 2);
17939         }
17940         else {
17941            vassert(bP == 0 && bW == 1);
17942            DIP("%s.w r%u, r%u, [r%u], #%c%u\n",
17943                nm, rT, rT2, rN, bU ? '+' : '-', imm8 << 2);
17944         }
17945
17946         goto decode_success;
17947      }
17948   }
17949
17950   /* -------------- (T3) Bcond.W label -------------- */
17951   /* This variant carries its own condition, so can't be part of an
17952      IT block ... */
17953   if (INSN0(15,11) == BITS5(1,1,1,1,0)
17954       && INSN1(15,14) == BITS2(1,0)
17955       && INSN1(12,12) == 0) {
17956      UInt cond = INSN0(9,6);
17957      if (cond != ARMCondAL && cond != ARMCondNV) {
17958         Int simm21
17959            =   (INSN0(10,10) << (1 + 1 + 6 + 11 + 1))
17960              | (INSN1(11,11) << (1 + 6 + 11 + 1))
17961              | (INSN1(13,13) << (6 + 11 + 1))
17962              | (INSN0(5,0)   << (11 + 1))
17963              | (INSN1(10,0)  << 1);
17964         simm21 = (simm21 << 11) >> 11;
17965
17966         vassert(0 == (guest_R15_curr_instr_notENC & 1));
17967         UInt dst = simm21 + guest_R15_curr_instr_notENC + 4;
17968
17969         /* Not allowed in an IT block; SIGILL if so. */
17970         gen_SIGILL_T_if_in_ITBlock(old_itstate, new_itstate);
17971
17972         IRTemp kondT = newTemp(Ity_I32);
17973         assign( kondT, mk_armg_calculate_condition(cond) );
17974         stmt( IRStmt_Exit( unop(Iop_32to1, mkexpr(kondT)),
17975                            Ijk_Boring,
17976                            IRConst_U32(dst | 1/*CPSR.T*/),
17977                            OFFB_R15T ));
17978         llPutIReg(15, mkU32( (guest_R15_curr_instr_notENC + 4)
17979                              | 1 /*CPSR.T*/ ));
17980         dres.jk_StopHere = Ijk_Boring;
17981         dres.whatNext    = Dis_StopHere;
17982         DIP("b%s.w 0x%x\n", nCC(cond), dst);
17983         goto decode_success;
17984      }
17985   }
17986
17987   /* ---------------- (T4) B.W label ---------------- */
17988   /* ... whereas this variant doesn't carry its own condition, so it
17989      has to be either unconditional or the conditional by virtue of
17990      being the last in an IT block.  The upside is that there's 4
17991      more bits available for the jump offset, so it has a 16-times
17992      greater branch range than the T3 variant. */
17993   if (INSN0(15,11) == BITS5(1,1,1,1,0)
17994       && INSN1(15,14) == BITS2(1,0)
17995       && INSN1(12,12) == 1) {
17996      if (1) {
17997         UInt bS  = INSN0(10,10);
17998         UInt bJ1 = INSN1(13,13);
17999         UInt bJ2 = INSN1(11,11);
18000         UInt bI1 = 1 ^ (bJ1 ^ bS);
18001         UInt bI2 = 1 ^ (bJ2 ^ bS);
18002         Int simm25
18003            =   (bS          << (1 + 1 + 10 + 11 + 1))
18004              | (bI1         << (1 + 10 + 11 + 1))
18005              | (bI2         << (10 + 11 + 1))
18006              | (INSN0(9,0)  << (11 + 1))
18007              | (INSN1(10,0) << 1);
18008         simm25 = (simm25 << 7) >> 7;
18009
18010         vassert(0 == (guest_R15_curr_instr_notENC & 1));
18011         UInt dst = simm25 + guest_R15_curr_instr_notENC + 4;
18012
18013         /* If in an IT block, must be the last insn. */
18014         gen_SIGILL_T_if_in_but_NLI_ITBlock(old_itstate, new_itstate);
18015
18016         // go uncond
18017         mk_skip_over_T32_if_cond_is_false(condT);
18018         condT = IRTemp_INVALID;
18019         // now uncond
18020
18021         // branch to dst
18022         llPutIReg(15, mkU32( dst | 1 /*CPSR.T*/ ));
18023         dres.jk_StopHere = Ijk_Boring;
18024         dres.whatNext    = Dis_StopHere;
18025         DIP("b.w 0x%x\n", dst);
18026         goto decode_success;
18027      }
18028   }
18029
18030   /* ------------------ TBB, TBH ------------------ */
18031   if (INSN0(15,4) == 0xE8D && INSN1(15,5) == 0x780) {
18032      UInt rN = INSN0(3,0);
18033      UInt rM = INSN1(3,0);
18034      UInt bH = INSN1(4,4);
18035      if (bH/*ATC*/ || (rN != 13 && !isBadRegT(rM))) {
18036         /* Must be last or not-in IT block */
18037         gen_SIGILL_T_if_in_but_NLI_ITBlock(old_itstate, new_itstate);
18038         /* Go uncond */
18039         mk_skip_over_T32_if_cond_is_false(condT);
18040         condT = IRTemp_INVALID;
18041
18042         IRExpr* ea
18043             = binop(Iop_Add32,
18044                     getIRegT(rN),
18045                     bH ? binop(Iop_Shl32, getIRegT(rM), mkU8(1))
18046                        : getIRegT(rM));
18047
18048         IRTemp delta = newTemp(Ity_I32);
18049         if (bH) {
18050            assign(delta, unop(Iop_16Uto32, loadLE(Ity_I16, ea)));
18051         } else {
18052            assign(delta, unop(Iop_8Uto32, loadLE(Ity_I8, ea)));
18053         }
18054
18055         llPutIReg(
18056            15,
18057            binop(Iop_Or32,
18058                  binop(Iop_Add32,
18059                        getIRegT(15),
18060                        binop(Iop_Shl32, mkexpr(delta), mkU8(1))
18061                  ),
18062                  mkU32(1)
18063         ));
18064         dres.jk_StopHere = Ijk_Boring;
18065         dres.whatNext    = Dis_StopHere;
18066         DIP("tb%c [r%u, r%u%s]\n",
18067             bH ? 'h' : 'b', rN, rM, bH ? ", LSL #1" : "");
18068         goto decode_success;
18069      }
18070   }
18071
18072   /* ------------------ UBFX ------------------ */
18073   /* ------------------ SBFX ------------------ */
18074   /* There's also ARM versions of same, but it doesn't seem worth the
18075      hassle to common up the handling (it's only a couple of C
18076      statements). */
18077   if ((INSN0(15,4) == 0xF3C // UBFX
18078        || INSN0(15,4) == 0xF34) // SBFX
18079       && INSN1(15,15) == 0 && INSN1(5,5) == 0) {
18080      UInt rN  = INSN0(3,0);
18081      UInt rD  = INSN1(11,8);
18082      UInt lsb = (INSN1(14,12) << 2) | INSN1(7,6);
18083      UInt wm1 = INSN1(4,0);
18084      UInt msb =  lsb + wm1;
18085      if (!isBadRegT(rD) && !isBadRegT(rN) && msb <= 31) {
18086         Bool   isU  = INSN0(15,4) == 0xF3C;
18087         IRTemp src  = newTemp(Ity_I32);
18088         IRTemp tmp  = newTemp(Ity_I32);
18089         IRTemp res  = newTemp(Ity_I32);
18090         UInt   mask = ((1 << wm1) - 1) + (1 << wm1);
18091         vassert(msb >= 0 && msb <= 31);
18092         vassert(mask != 0); // guaranteed by msb being in 0 .. 31 inclusive
18093
18094         assign(src, getIRegT(rN));
18095         assign(tmp, binop(Iop_And32,
18096                           binop(Iop_Shr32, mkexpr(src), mkU8(lsb)),
18097                           mkU32(mask)));
18098         assign(res, binop(isU ? Iop_Shr32 : Iop_Sar32,
18099                           binop(Iop_Shl32, mkexpr(tmp), mkU8(31-wm1)),
18100                           mkU8(31-wm1)));
18101
18102         putIRegT(rD, mkexpr(res), condT);
18103
18104         DIP("%s r%u, r%u, #%u, #%u\n",
18105             isU ? "ubfx" : "sbfx", rD, rN, lsb, wm1 + 1);
18106         goto decode_success;
18107      }
18108   }
18109
18110   /* ------------------ UXTB ------------------ */
18111   /* ------------------ UXTH ------------------ */
18112   /* ------------------ SXTB ------------------ */
18113   /* ------------------ SXTH ------------------ */
18114   /* ----------------- UXTB16 ----------------- */
18115   /* ----------------- SXTB16 ----------------- */
18116   /* FIXME: this is an exact duplicate of the ARM version.  They
18117      should be commoned up. */
18118   if ((INSN0(15,0) == 0xFA5F     // UXTB
18119        || INSN0(15,0) == 0xFA1F  // UXTH
18120        || INSN0(15,0) == 0xFA4F  // SXTB
18121        || INSN0(15,0) == 0xFA0F  // SXTH
18122        || INSN0(15,0) == 0xFA3F  // UXTB16
18123        || INSN0(15,0) == 0xFA2F) // SXTB16
18124       && INSN1(15,12) == BITS4(1,1,1,1)
18125       && INSN1(7,6) == BITS2(1,0)) {
18126      UInt rD = INSN1(11,8);
18127      UInt rM = INSN1(3,0);
18128      UInt rot = INSN1(5,4);
18129      if (!isBadRegT(rD) && !isBadRegT(rM)) {
18130         HChar* nm = "???";
18131         IRTemp srcT = newTemp(Ity_I32);
18132         IRTemp rotT = newTemp(Ity_I32);
18133         IRTemp dstT = newTemp(Ity_I32);
18134         assign(srcT, getIRegT(rM));
18135         assign(rotT, genROR32(srcT, 8 * rot));
18136         switch (INSN0(15,0)) {
18137            case 0xFA5F: // UXTB
18138               nm = "uxtb";
18139               assign(dstT, unop(Iop_8Uto32,
18140                                 unop(Iop_32to8, mkexpr(rotT))));
18141               break;
18142            case 0xFA1F: // UXTH
18143               nm = "uxth";
18144               assign(dstT, unop(Iop_16Uto32,
18145                                 unop(Iop_32to16, mkexpr(rotT))));
18146               break;
18147            case 0xFA4F: // SXTB
18148               nm = "sxtb";
18149               assign(dstT, unop(Iop_8Sto32,
18150                                 unop(Iop_32to8, mkexpr(rotT))));
18151               break;
18152            case 0xFA0F: // SXTH
18153               nm = "sxth";
18154               assign(dstT, unop(Iop_16Sto32,
18155                                 unop(Iop_32to16, mkexpr(rotT))));
18156               break;
18157            case 0xFA3F: // UXTB16
18158               nm = "uxtb16";
18159               assign(dstT, binop(Iop_And32, mkexpr(rotT),
18160                                             mkU32(0x00FF00FF)));
18161               break;
18162            case 0xFA2F: { // SXTB16
18163               nm = "sxtb16";
18164               IRTemp lo32 = newTemp(Ity_I32);
18165               IRTemp hi32 = newTemp(Ity_I32);
18166               assign(lo32, binop(Iop_And32, mkexpr(rotT), mkU32(0xFF)));
18167               assign(hi32, binop(Iop_Shr32, mkexpr(rotT), mkU8(16)));
18168               assign(
18169                  dstT,
18170                  binop(Iop_Or32,
18171                        binop(Iop_And32,
18172                              unop(Iop_8Sto32,
18173                                   unop(Iop_32to8, mkexpr(lo32))),
18174                              mkU32(0xFFFF)),
18175                        binop(Iop_Shl32,
18176                              unop(Iop_8Sto32,
18177                                   unop(Iop_32to8, mkexpr(hi32))),
18178                              mkU8(16))
18179               ));
18180               break;
18181            }
18182            default:
18183               vassert(0);
18184         }
18185         putIRegT(rD, mkexpr(dstT), condT);
18186         DIP("%s r%u, r%u, ror #%u\n", nm, rD, rM, 8 * rot);
18187         goto decode_success;
18188      }
18189   }
18190
18191   /* -------------- MUL.W Rd, Rn, Rm -------------- */
18192   if (INSN0(15,4) == 0xFB0
18193       && (INSN1(15,0) & 0xF0F0) == 0xF000) {
18194      UInt rN = INSN0(3,0);
18195      UInt rD = INSN1(11,8);
18196      UInt rM = INSN1(3,0);
18197      if (!isBadRegT(rD) && !isBadRegT(rN) && !isBadRegT(rM)) {
18198         IRTemp res = newTemp(Ity_I32);
18199         assign(res, binop(Iop_Mul32, getIRegT(rN), getIRegT(rM)));
18200         putIRegT(rD, mkexpr(res), condT);
18201         DIP("mul.w r%u, r%u, r%u\n", rD, rN, rM);
18202         goto decode_success;
18203      }
18204   }
18205
18206   /* -------------- SDIV.W Rd, Rn, Rm -------------- */
18207   if (INSN0(15,4) == 0xFB9
18208       && (INSN1(15,0) & 0xF0F0) == 0xF0F0) {
18209      UInt rN = INSN0(3,0);
18210      UInt rD = INSN1(11,8);
18211      UInt rM = INSN1(3,0);
18212      if (!isBadRegT(rD) && !isBadRegT(rN) && !isBadRegT(rM)) {
18213         IRTemp res = newTemp(Ity_I32);
18214         IRTemp argL  = newTemp(Ity_I32);
18215         IRTemp argR  = newTemp(Ity_I32);
18216         assign(argL, getIRegT(rN));
18217         assign(argR, getIRegT(rM));
18218         assign(res, binop(Iop_DivS32, mkexpr(argL), mkexpr(argR)));
18219         putIRegT(rD, mkexpr(res), condT);
18220         DIP("sdiv.w r%u, r%u, r%u\n", rD, rN, rM);
18221         goto decode_success;
18222      }
18223   }
18224
18225   /* -------------- UDIV.W Rd, Rn, Rm -------------- */
18226   if (INSN0(15,4) == 0xFBB
18227       && (INSN1(15,0) & 0xF0F0) == 0xF0F0) {
18228      UInt rN = INSN0(3,0);
18229      UInt rD = INSN1(11,8);
18230      UInt rM = INSN1(3,0);
18231      if (!isBadRegT(rD) && !isBadRegT(rN) && !isBadRegT(rM)) {
18232         IRTemp res = newTemp(Ity_I32);
18233         IRTemp argL  = newTemp(Ity_I32);
18234         IRTemp argR  = newTemp(Ity_I32);
18235         assign(argL, getIRegT(rN));
18236         assign(argR, getIRegT(rM));
18237         assign(res, binop(Iop_DivU32, mkexpr(argL), mkexpr(argR)));
18238         putIRegT(rD, mkexpr(res), condT);
18239         DIP("udiv.w r%u, r%u, r%u\n", rD, rN, rM);
18240         goto decode_success;
18241      }
18242   }
18243
18244   /* ------------------ {U,S}MULL ------------------ */
18245   if ((INSN0(15,4) == 0xFB8 || INSN0(15,4) == 0xFBA)
18246       && INSN1(7,4) == BITS4(0,0,0,0)) {
18247      UInt isU  = INSN0(5,5);
18248      UInt rN   = INSN0(3,0);
18249      UInt rDlo = INSN1(15,12);
18250      UInt rDhi = INSN1(11,8);
18251      UInt rM   = INSN1(3,0);
18252      if (!isBadRegT(rDhi) && !isBadRegT(rDlo)
18253          && !isBadRegT(rN) && !isBadRegT(rM) && rDlo != rDhi) {
18254         IRTemp res   = newTemp(Ity_I64);
18255         assign(res, binop(isU ? Iop_MullU32 : Iop_MullS32,
18256                           getIRegT(rN), getIRegT(rM)));
18257         putIRegT( rDhi, unop(Iop_64HIto32, mkexpr(res)), condT );
18258         putIRegT( rDlo, unop(Iop_64to32, mkexpr(res)), condT );
18259         DIP("%cmull r%u, r%u, r%u, r%u\n",
18260             isU ? 'u' : 's', rDlo, rDhi, rN, rM);
18261         goto decode_success;
18262      }
18263   }
18264
18265   /* ------------------ ML{A,S} ------------------ */
18266   if (INSN0(15,4) == 0xFB0
18267       && (   INSN1(7,4) == BITS4(0,0,0,0)    // MLA
18268           || INSN1(7,4) == BITS4(0,0,0,1))) { // MLS
18269      UInt rN = INSN0(3,0);
18270      UInt rA = INSN1(15,12);
18271      UInt rD = INSN1(11,8);
18272      UInt rM = INSN1(3,0);
18273      if (!isBadRegT(rD) && !isBadRegT(rN)
18274          && !isBadRegT(rM) && !isBadRegT(rA)) {
18275         Bool   isMLA = INSN1(7,4) == BITS4(0,0,0,0);
18276         IRTemp res   = newTemp(Ity_I32);
18277         assign(res,
18278                binop(isMLA ? Iop_Add32 : Iop_Sub32,
18279                      getIRegT(rA),
18280                      binop(Iop_Mul32, getIRegT(rN), getIRegT(rM))));
18281         putIRegT(rD, mkexpr(res), condT);
18282         DIP("%s r%u, r%u, r%u, r%u\n",
18283             isMLA ? "mla" : "mls", rD, rN, rM, rA);
18284         goto decode_success;
18285      }
18286   }
18287
18288   /* ------------------ (T3) ADR ------------------ */
18289   if ((INSN0(15,0) == 0xF20F || INSN0(15,0) == 0xF60F)
18290       && INSN1(15,15) == 0) {
18291      /* rD = align4(PC) + imm32 */
18292      UInt rD = INSN1(11,8);
18293      if (!isBadRegT(rD)) {
18294         UInt imm32 = (INSN0(10,10) << 11)
18295                      | (INSN1(14,12) << 8) | INSN1(7,0);
18296         putIRegT(rD, binop(Iop_Add32,
18297                            binop(Iop_And32, getIRegT(15), mkU32(~3U)),
18298                            mkU32(imm32)),
18299                      condT);
18300         DIP("add r%u, pc, #%u\n", rD, imm32);
18301         goto decode_success;
18302      }
18303   }
18304
18305   /* ----------------- (T1) UMLAL ----------------- */
18306   /* ----------------- (T1) SMLAL ----------------- */
18307   if ((INSN0(15,4) == 0xFBE // UMLAL
18308        || INSN0(15,4) == 0xFBC) // SMLAL
18309       && INSN1(7,4) == BITS4(0,0,0,0)) {
18310      UInt rN   = INSN0(3,0);
18311      UInt rDlo = INSN1(15,12);
18312      UInt rDhi = INSN1(11,8);
18313      UInt rM   = INSN1(3,0);
18314      if (!isBadRegT(rDlo) && !isBadRegT(rDhi) && !isBadRegT(rN)
18315          && !isBadRegT(rM) && rDhi != rDlo) {
18316         Bool   isS   = INSN0(15,4) == 0xFBC;
18317         IRTemp argL  = newTemp(Ity_I32);
18318         IRTemp argR  = newTemp(Ity_I32);
18319         IRTemp old   = newTemp(Ity_I64);
18320         IRTemp res   = newTemp(Ity_I64);
18321         IRTemp resHi = newTemp(Ity_I32);
18322         IRTemp resLo = newTemp(Ity_I32);
18323         IROp   mulOp = isS ? Iop_MullS32 : Iop_MullU32;
18324         assign( argL, getIRegT(rM));
18325         assign( argR, getIRegT(rN));
18326         assign( old, binop(Iop_32HLto64, getIRegT(rDhi), getIRegT(rDlo)) );
18327         assign( res, binop(Iop_Add64,
18328                            mkexpr(old),
18329                            binop(mulOp, mkexpr(argL), mkexpr(argR))) );
18330         assign( resHi, unop(Iop_64HIto32, mkexpr(res)) );
18331         assign( resLo, unop(Iop_64to32, mkexpr(res)) );
18332         putIRegT( rDhi, mkexpr(resHi), condT );
18333         putIRegT( rDlo, mkexpr(resLo), condT );
18334         DIP("%cmlal r%u, r%u, r%u, r%u\n",
18335             isS ? 's' : 'u', rDlo, rDhi, rN, rM);
18336         goto decode_success;
18337      }
18338   }
18339
18340   /* ------------------ (T2) ADR ------------------ */
18341   if ((INSN0(15,0) == 0xF2AF || INSN0(15,0) == 0xF6AF)
18342       && INSN1(15,15) == 0) {
18343      /* rD = align4(PC) - imm32 */
18344      UInt rD = INSN1(11,8);
18345      if (!isBadRegT(rD)) {
18346         UInt imm32 = (INSN0(10,10) << 11)
18347                      | (INSN1(14,12) << 8) | INSN1(7,0);
18348         putIRegT(rD, binop(Iop_Sub32,
18349                            binop(Iop_And32, getIRegT(15), mkU32(~3U)),
18350                            mkU32(imm32)),
18351                      condT);
18352         DIP("sub r%u, pc, #%u\n", rD, imm32);
18353         goto decode_success;
18354      }
18355   }
18356
18357   /* ------------------- (T1) BFI ------------------- */
18358   /* ------------------- (T1) BFC ------------------- */
18359   if (INSN0(15,4) == 0xF36 && INSN1(15,15) == 0 && INSN1(5,5) == 0) {
18360      UInt rD  = INSN1(11,8);
18361      UInt rN  = INSN0(3,0);
18362      UInt msb = INSN1(4,0);
18363      UInt lsb = (INSN1(14,12) << 2) | INSN1(7,6);
18364      if (isBadRegT(rD) || rN == 13 || msb < lsb) {
18365         /* undecodable; fall through */
18366      } else {
18367         IRTemp src    = newTemp(Ity_I32);
18368         IRTemp olddst = newTemp(Ity_I32);
18369         IRTemp newdst = newTemp(Ity_I32);
18370         UInt   mask = 1 << (msb - lsb);
18371         mask = (mask - 1) + mask;
18372         vassert(mask != 0); // guaranteed by "msb < lsb" check above
18373         mask <<= lsb;
18374
18375         assign(src, rN == 15 ? mkU32(0) : getIRegT(rN));
18376         assign(olddst, getIRegT(rD));
18377         assign(newdst,
18378                binop(Iop_Or32,
18379                   binop(Iop_And32,
18380                         binop(Iop_Shl32, mkexpr(src), mkU8(lsb)),
18381                         mkU32(mask)),
18382                   binop(Iop_And32,
18383                         mkexpr(olddst),
18384                         mkU32(~mask)))
18385               );
18386
18387         putIRegT(rD, mkexpr(newdst), condT);
18388
18389         if (rN == 15) {
18390            DIP("bfc r%u, #%u, #%u\n",
18391                rD, lsb, msb-lsb+1);
18392         } else {
18393            DIP("bfi r%u, r%u, #%u, #%u\n",
18394                rD, rN, lsb, msb-lsb+1);
18395         }
18396         goto decode_success;
18397      }
18398   }
18399
18400   /* ------------------- (T1) SXTAH ------------------- */
18401   /* ------------------- (T1) UXTAH ------------------- */
18402   if ((INSN0(15,4) == 0xFA1      // UXTAH
18403        || INSN0(15,4) == 0xFA0)  // SXTAH
18404       && INSN1(15,12) == BITS4(1,1,1,1)
18405       && INSN1(7,6) == BITS2(1,0)) {
18406      Bool isU = INSN0(15,4) == 0xFA1;
18407      UInt rN  = INSN0(3,0);
18408      UInt rD  = INSN1(11,8);
18409      UInt rM  = INSN1(3,0);
18410      UInt rot = INSN1(5,4);
18411      if (!isBadRegT(rD) && !isBadRegT(rN) && !isBadRegT(rM)) {
18412         IRTemp srcL = newTemp(Ity_I32);
18413         IRTemp srcR = newTemp(Ity_I32);
18414         IRTemp res  = newTemp(Ity_I32);
18415         assign(srcR, getIRegT(rM));
18416         assign(srcL, getIRegT(rN));
18417         assign(res,  binop(Iop_Add32,
18418                            mkexpr(srcL),
18419                            unop(isU ? Iop_16Uto32 : Iop_16Sto32,
18420                                 unop(Iop_32to16,
18421                                      genROR32(srcR, 8 * rot)))));
18422         putIRegT(rD, mkexpr(res), condT);
18423         DIP("%cxtah r%u, r%u, r%u, ror #%u\n",
18424             isU ? 'u' : 's', rD, rN, rM, rot);
18425         goto decode_success;
18426      }
18427   }
18428
18429   /* ------------------- (T1) SXTAB ------------------- */
18430   /* ------------------- (T1) UXTAB ------------------- */
18431   if ((INSN0(15,4) == 0xFA5      // UXTAB
18432        || INSN0(15,4) == 0xFA4)  // SXTAB
18433       && INSN1(15,12) == BITS4(1,1,1,1)
18434       && INSN1(7,6) == BITS2(1,0)) {
18435      Bool isU = INSN0(15,4) == 0xFA5;
18436      UInt rN  = INSN0(3,0);
18437      UInt rD  = INSN1(11,8);
18438      UInt rM  = INSN1(3,0);
18439      UInt rot = INSN1(5,4);
18440      if (!isBadRegT(rD) && !isBadRegT(rN) && !isBadRegT(rM)) {
18441         IRTemp srcL = newTemp(Ity_I32);
18442         IRTemp srcR = newTemp(Ity_I32);
18443         IRTemp res  = newTemp(Ity_I32);
18444         assign(srcR, getIRegT(rM));
18445         assign(srcL, getIRegT(rN));
18446         assign(res,  binop(Iop_Add32,
18447                            mkexpr(srcL),
18448                            unop(isU ? Iop_8Uto32 : Iop_8Sto32,
18449                                 unop(Iop_32to8,
18450                                      genROR32(srcR, 8 * rot)))));
18451         putIRegT(rD, mkexpr(res), condT);
18452         DIP("%cxtab r%u, r%u, r%u, ror #%u\n",
18453             isU ? 'u' : 's', rD, rN, rM, rot);
18454         goto decode_success;
18455      }
18456   }
18457
18458   /* ------------------- (T1) CLZ ------------------- */
18459   if (INSN0(15,4) == 0xFAB
18460       && INSN1(15,12) == BITS4(1,1,1,1)
18461       && INSN1(7,4) == BITS4(1,0,0,0)) {
18462      UInt rM1 = INSN0(3,0);
18463      UInt rD  = INSN1(11,8);
18464      UInt rM2 = INSN1(3,0);
18465      if (!isBadRegT(rD) && !isBadRegT(rM1) && rM1 == rM2) {
18466         IRTemp arg = newTemp(Ity_I32);
18467         IRTemp res = newTemp(Ity_I32);
18468         assign(arg, getIRegT(rM1));
18469         assign(res, IRExpr_Mux0X(
18470                        unop(Iop_1Uto8,binop(Iop_CmpEQ32,
18471                                             mkexpr(arg),
18472                                             mkU32(0))),
18473                        unop(Iop_Clz32, mkexpr(arg)),
18474                        mkU32(32)
18475         ));
18476         putIRegT(rD, mkexpr(res), condT);
18477         DIP("clz r%u, r%u\n", rD, rM1);
18478         goto decode_success;
18479      }
18480   }
18481
18482   /* ------------------- (T1) RBIT ------------------- */
18483   if (INSN0(15,4) == 0xFA9
18484       && INSN1(15,12) == BITS4(1,1,1,1)
18485       && INSN1(7,4) == BITS4(1,0,1,0)) {
18486      UInt rM1 = INSN0(3,0);
18487      UInt rD  = INSN1(11,8);
18488      UInt rM2 = INSN1(3,0);
18489      if (!isBadRegT(rD) && !isBadRegT(rM1) && rM1 == rM2) {
18490         IRTemp arg = newTemp(Ity_I32);
18491         assign(arg, getIRegT(rM1));
18492         IRTemp res = gen_BITREV(arg);
18493         putIRegT(rD, mkexpr(res), condT);
18494         DIP("rbit r%u, r%u\n", rD, rM1);
18495         goto decode_success;
18496      }
18497   }
18498
18499   /* ------------------- (T2) REV   ------------------- */
18500   /* ------------------- (T2) REV16 ------------------- */
18501   if (INSN0(15,4) == 0xFA9
18502       && INSN1(15,12) == BITS4(1,1,1,1)
18503       && (   INSN1(7,4) == BITS4(1,0,0,0)     // REV
18504           || INSN1(7,4) == BITS4(1,0,0,1))) { // REV16
18505      UInt rM1   = INSN0(3,0);
18506      UInt rD    = INSN1(11,8);
18507      UInt rM2   = INSN1(3,0);
18508      Bool isREV = INSN1(7,4) == BITS4(1,0,0,0);
18509      if (!isBadRegT(rD) && !isBadRegT(rM1) && rM1 == rM2) {
18510         IRTemp arg = newTemp(Ity_I32);
18511         assign(arg, getIRegT(rM1));
18512         IRTemp res = isREV ? gen_REV(arg) : gen_REV16(arg);
18513         putIRegT(rD, mkexpr(res), condT);
18514         DIP("rev%s r%u, r%u\n", isREV ? "" : "16", rD, rM1);
18515         goto decode_success;
18516      }
18517   }
18518
18519   /* -------------- (T1) MSR apsr, reg -------------- */
18520   if (INSN0(15,4) == 0xF38
18521       && INSN1(15,12) == BITS4(1,0,0,0) && INSN1(9,0) == 0x000) {
18522      UInt rN          = INSN0(3,0);
18523      UInt write_ge    = INSN1(10,10);
18524      UInt write_nzcvq = INSN1(11,11);
18525      if (!isBadRegT(rN) && (write_nzcvq || write_ge)) {
18526         IRTemp rNt = newTemp(Ity_I32);
18527         assign(rNt, getIRegT(rN));
18528         desynthesise_APSR( write_nzcvq, write_ge, rNt, condT );
18529         DIP("msr cpsr_%s%s, r%u\n",
18530             write_nzcvq ? "f" : "", write_ge ? "g" : "", rN);
18531         goto decode_success;
18532      }
18533   }
18534
18535   /* -------------- (T1) MRS reg, apsr -------------- */
18536   if (INSN0(15,0) == 0xF3EF
18537       && INSN1(15,12) == BITS4(1,0,0,0) && INSN1(7,0) == 0x00) {
18538      UInt rD = INSN1(11,8);
18539      if (!isBadRegT(rD)) {
18540         IRTemp apsr = synthesise_APSR();
18541         putIRegT( rD, mkexpr(apsr), condT );
18542         DIP("mrs r%u, cpsr\n", rD);
18543         goto decode_success;
18544      }
18545   }
18546
18547   /* ----------------- (T1) LDREX ----------------- */
18548   if (INSN0(15,4) == 0xE85 && INSN1(11,8) == BITS4(1,1,1,1)) {
18549      UInt rN   = INSN0(3,0);
18550      UInt rT   = INSN1(15,12);
18551      UInt imm8 = INSN1(7,0);
18552      if (!isBadRegT(rT) && rN != 15) {
18553         IRTemp res;
18554         // go uncond
18555         mk_skip_over_T32_if_cond_is_false( condT );
18556         // now uncond
18557         res = newTemp(Ity_I32);
18558         stmt( IRStmt_LLSC(Iend_LE,
18559                           res,
18560                           binop(Iop_Add32, getIRegT(rN), mkU32(imm8 * 4)),
18561                           NULL/*this is a load*/ ));
18562         putIRegT(rT, mkexpr(res), IRTemp_INVALID);
18563         DIP("ldrex r%u, [r%u, #+%u]\n", rT, rN, imm8 * 4);
18564         goto decode_success;
18565      }
18566   }
18567
18568   /* --------------- (T1) LDREX{B,H} --------------- */
18569   if (INSN0(15,4) == 0xE8D
18570       && (INSN1(11,0) == 0xF4F || INSN1(11,0) == 0xF5F)) {
18571      UInt rN  = INSN0(3,0);
18572      UInt rT  = INSN1(15,12);
18573      Bool isH = INSN1(11,0) == 0xF5F;
18574      if (!isBadRegT(rT) && rN != 15) {
18575         IRTemp res;
18576         // go uncond
18577         mk_skip_over_T32_if_cond_is_false( condT );
18578         // now uncond
18579         res = newTemp(isH ? Ity_I16 : Ity_I8);
18580         stmt( IRStmt_LLSC(Iend_LE, res, getIRegT(rN),
18581                           NULL/*this is a load*/ ));
18582         putIRegT(rT, unop(isH ? Iop_16Uto32 : Iop_8Uto32, mkexpr(res)),
18583                      IRTemp_INVALID);
18584         DIP("ldrex%c r%u, [r%u]\n", isH ? 'h' : 'b', rT, rN);
18585         goto decode_success;
18586      }
18587   }
18588
18589   /* --------------- (T1) LDREXD --------------- */
18590   if (INSN0(15,4) == 0xE8D && INSN1(7,0) == 0x7F) {
18591      UInt rN  = INSN0(3,0);
18592      UInt rT  = INSN1(15,12);
18593      UInt rT2 = INSN1(11,8);
18594      if (!isBadRegT(rT) && !isBadRegT(rT2) && rT != rT2 && rN != 15) {
18595         IRTemp res;
18596         // go uncond
18597         mk_skip_over_T32_if_cond_is_false( condT );
18598         // now uncond
18599         res = newTemp(Ity_I64);
18600         // FIXME: assumes little-endian guest
18601         stmt( IRStmt_LLSC(Iend_LE, res, getIRegT(rN),
18602                           NULL/*this is a load*/ ));
18603         // FIXME: assumes little-endian guest
18604         putIRegT(rT,  unop(Iop_64to32,   mkexpr(res)), IRTemp_INVALID);
18605         putIRegT(rT2, unop(Iop_64HIto32, mkexpr(res)), IRTemp_INVALID);
18606         DIP("ldrexd r%u, r%u, [r%u]\n", rT, rT2, rN);
18607         goto decode_success;
18608      }
18609   }
18610
18611   /* ----------------- (T1) STREX ----------------- */
18612   if (INSN0(15,4) == 0xE84) {
18613      UInt rN   = INSN0(3,0);
18614      UInt rT   = INSN1(15,12);
18615      UInt rD   = INSN1(11,8);
18616      UInt imm8 = INSN1(7,0);
18617      if (!isBadRegT(rD) && !isBadRegT(rT) && rN != 15
18618          && rD != rN && rD != rT) {
18619         IRTemp resSC1, resSC32;
18620         // go uncond
18621         mk_skip_over_T32_if_cond_is_false( condT );
18622         // now uncond
18623         /* Ok, now we're unconditional.  Do the store. */
18624         resSC1 = newTemp(Ity_I1);
18625         stmt( IRStmt_LLSC(Iend_LE,
18626                           resSC1,
18627                           binop(Iop_Add32, getIRegT(rN), mkU32(imm8 * 4)),
18628                           getIRegT(rT)) );
18629         /* Set rD to 1 on failure, 0 on success.  Currently we have
18630            resSC1 == 0 on failure, 1 on success. */
18631         resSC32 = newTemp(Ity_I32);
18632         assign(resSC32,
18633                unop(Iop_1Uto32, unop(Iop_Not1, mkexpr(resSC1))));
18634         putIRegT(rD, mkexpr(resSC32), IRTemp_INVALID);
18635         DIP("strex r%u, r%u, [r%u, #+%u]\n", rD, rT, rN, imm8 * 4);
18636         goto decode_success;
18637      }
18638   }
18639
18640   /* --------------- (T1) STREX{B,H} --------------- */
18641   if (INSN0(15,4) == 0xE8C
18642       && (INSN1(11,4) == 0xF4 || INSN1(11,4) == 0xF5)) {
18643      UInt rN  = INSN0(3,0);
18644      UInt rT  = INSN1(15,12);
18645      UInt rD  = INSN1(3,0);
18646      Bool isH = INSN1(11,4) == 0xF5;
18647      if (!isBadRegT(rD) && !isBadRegT(rT) && rN != 15
18648          && rD != rN && rD != rT) {
18649         IRTemp resSC1, resSC32;
18650         // go uncond
18651         mk_skip_over_T32_if_cond_is_false( condT );
18652         // now uncond
18653         /* Ok, now we're unconditional.  Do the store. */
18654         resSC1 = newTemp(Ity_I1);
18655         stmt( IRStmt_LLSC(Iend_LE, resSC1, getIRegT(rN),
18656                           unop(isH ? Iop_32to16 : Iop_32to8,
18657                                getIRegT(rT))) );
18658         /* Set rD to 1 on failure, 0 on success.  Currently we have
18659            resSC1 == 0 on failure, 1 on success. */
18660         resSC32 = newTemp(Ity_I32);
18661         assign(resSC32,
18662                unop(Iop_1Uto32, unop(Iop_Not1, mkexpr(resSC1))));
18663         putIRegT(rD, mkexpr(resSC32), IRTemp_INVALID);
18664         DIP("strex%c r%u, r%u, [r%u]\n", isH ? 'h' : 'b', rD, rT, rN);
18665         goto decode_success;
18666      }
18667   }
18668
18669   /* ---------------- (T1) STREXD ---------------- */
18670   if (INSN0(15,4) == 0xE8C && INSN1(7,4) == BITS4(0,1,1,1)) {
18671      UInt rN  = INSN0(3,0);
18672      UInt rT  = INSN1(15,12);
18673      UInt rT2 = INSN1(11,8);
18674      UInt rD  = INSN1(3,0);
18675      if (!isBadRegT(rD) && !isBadRegT(rT) && !isBadRegT(rT2)
18676          && rN != 15 && rD != rN && rD != rT && rD != rT) {
18677         IRTemp resSC1, resSC32, data;
18678         // go uncond
18679         mk_skip_over_T32_if_cond_is_false( condT );
18680         // now uncond
18681         /* Ok, now we're unconditional.  Do the store. */
18682         resSC1 = newTemp(Ity_I1);
18683         data = newTemp(Ity_I64);
18684         // FIXME: assumes little-endian guest
18685         assign(data, binop(Iop_32HLto64, getIRegT(rT2), getIRegT(rT)));
18686         // FIXME: assumes little-endian guest
18687         stmt( IRStmt_LLSC(Iend_LE, resSC1, getIRegT(rN), mkexpr(data)));
18688         /* Set rD to 1 on failure, 0 on success.  Currently we have
18689            resSC1 == 0 on failure, 1 on success. */
18690         resSC32 = newTemp(Ity_I32);
18691         assign(resSC32,
18692                unop(Iop_1Uto32, unop(Iop_Not1, mkexpr(resSC1))));
18693         putIRegT(rD, mkexpr(resSC32), IRTemp_INVALID);
18694         DIP("strexd r%u, r%u, r%u, [r%u]\n", rD, rT, rT2, rN);
18695         goto decode_success;
18696      }
18697   }
18698   /* -------------- v7 barrier insns -------------- */
18699   if (INSN0(15,0) == 0xF3BF && (INSN1(15,0) & 0xFF00) == 0x8F00) {
18700      /* FIXME: should this be unconditional? */
18701      /* XXX this isn't really right, is it?  The generated IR does
18702         them unconditionally.  I guess it doesn't matter since it
18703         doesn't do any harm to do them even when the guarding
18704         condition is false -- it's just a performance loss. */
18705      switch (INSN1(7,0)) {
18706         case 0x4F: /* DSB sy */
18707         case 0x4E: /* DSB st */
18708         case 0x4B: /* DSB ish */
18709         case 0x4A: /* DSB ishst */
18710         case 0x47: /* DSB nsh */
18711         case 0x46: /* DSB nshst */
18712         case 0x43: /* DSB osh */
18713         case 0x42: /* DSB oshst */
18714            stmt( IRStmt_MBE(Imbe_Fence) );
18715            DIP("DSB\n");
18716            goto decode_success;
18717         case 0x5F: /* DMB sy */
18718         case 0x5E: /* DMB st */
18719         case 0x5B: /* DMB ish */
18720         case 0x5A: /* DMB ishst */
18721         case 0x57: /* DMB nsh */
18722         case 0x56: /* DMB nshst */
18723         case 0x53: /* DMB osh */
18724         case 0x52: /* DMB oshst */
18725            stmt( IRStmt_MBE(Imbe_Fence) );
18726            DIP("DMB\n");
18727            goto decode_success;
18728         case 0x6F: /* ISB */
18729            stmt( IRStmt_MBE(Imbe_Fence) );
18730            DIP("ISB\n");
18731            goto decode_success;
18732         default:
18733            break;
18734      }
18735   }
18736
18737   /* ---------------------- PLD{,W} ---------------------- */
18738   if ((INSN0(15,4) & 0xFFD) == 0xF89 && INSN1(15,12) == 0xF) {
18739      /* FIXME: should this be unconditional? */
18740      /* PLD/PLDW immediate, encoding T1 */
18741      UInt rN    = INSN0(3,0);
18742      UInt bW    = INSN0(5,5);
18743      UInt imm12 = INSN1(11,0);
18744      DIP("pld%s [r%u, #%u]\n", bW ? "w" : "",  rN, imm12);
18745      goto decode_success;
18746   }
18747
18748   if ((INSN0(15,4) & 0xFFD) == 0xF81 && INSN1(15,8) == 0xFC) {
18749      /* FIXME: should this be unconditional? */
18750      /* PLD/PLDW immediate, encoding T2 */
18751      UInt rN    = INSN0(3,0);
18752      UInt bW    = INSN0(5,5);
18753      UInt imm8  = INSN1(7,0);
18754      DIP("pld%s [r%u, #-%u]\n", bW ? "w" : "",  rN, imm8);
18755      goto decode_success;
18756   }
18757
18758   if ((INSN0(15,4) & 0xFFD) == 0xF81 && INSN1(15,6) == 0x3C0) {
18759      /* FIXME: should this be unconditional? */
18760      /* PLD/PLDW register, encoding T1 */
18761      UInt rN   = INSN0(3,0);
18762      UInt rM   = INSN1(3,0);
18763      UInt bW   = INSN0(5,5);
18764      UInt imm2 = INSN1(5,4);
18765      if (!isBadRegT(rM)) {
18766         DIP("pld%s [r%u, r%u, lsl %d]\n", bW ? "w" : "", rN, rM, imm2);
18767         goto decode_success;
18768      }
18769      /* fall through */
18770   }
18771
18772   /* -------------- read CP15 TPIDRURO register ------------- */
18773   /* mrc     p15, 0,  r0, c13, c0, 3  up to
18774      mrc     p15, 0, r14, c13, c0, 3
18775   */
18776   /* I don't know whether this is really v7-only.  But anyway, we
18777      have to support it since arm-linux uses TPIDRURO as a thread
18778      state register. */
18779   if ((INSN0(15,0) == 0xEE1D) && (INSN1(11,0) == 0x0F70)) {
18780      /* FIXME: should this be unconditional? */
18781      UInt rD = INSN1(15,12);
18782      if (!isBadRegT(rD)) {
18783         putIRegT(rD, IRExpr_Get(OFFB_TPIDRURO, Ity_I32), IRTemp_INVALID);
18784         DIP("mrc p15,0, r%u, c13, c0, 3\n", rD);
18785         goto decode_success;
18786      }
18787      /* fall through */
18788   }
18789
18790   /* ------------------- CLREX ------------------ */
18791   if (INSN0(15,0) == 0xF3BF && INSN1(15,0) == 0x8F2F) {
18792      /* AFAICS, this simply cancels a (all?) reservations made by a
18793         (any?) preceding LDREX(es).  Arrange to hand it through to
18794         the back end. */
18795      mk_skip_over_T32_if_cond_is_false( condT );
18796      stmt( IRStmt_MBE(Imbe_CancelReservation) );
18797      DIP("clrex\n");
18798      goto decode_success;
18799   }
18800
18801   /* ------------------- NOP ------------------ */
18802   if (INSN0(15,0) == 0xF3AF && INSN1(15,0) == 0x8000) {
18803      DIP("nop\n");
18804      goto decode_success;
18805   }
18806
18807   /* ------------------- (T1) SMMUL{R} ------------------ */
18808   if (INSN0(15,7) == BITS9(1,1,1,1,1,0,1,1,0)
18809       && INSN0(6,4) == BITS3(1,0,1)
18810       && INSN1(15,12) == BITS4(1,1,1,1)
18811       && INSN1(7,5) == BITS3(0,0,0)) {
18812      UInt bitR = INSN1(4,4);
18813      UInt rD = INSN1(11,8);
18814      UInt rM = INSN1(3,0);
18815      UInt rN = INSN0(3,0);
18816      if (!isBadRegT(rD) && !isBadRegT(rN) && !isBadRegT(rM)) {
18817         IRExpr* res
18818         = unop(Iop_64HIto32,
18819                binop(Iop_Add64,
18820                      binop(Iop_MullS32, getIRegT(rN), getIRegT(rM)),
18821                      mkU64(bitR ? 0x80000000ULL : 0ULL)));
18822         putIRegT(rD, res, condT);
18823         DIP("smmul%s r%u, r%u, r%u\n",
18824             bitR ? "r" : "", rD, rN, rM);
18825         goto decode_success;
18826      }
18827   }
18828
18829   /* ------------------- (T1) SMMLA{R} ------------------ */
18830   if (INSN0(15,7) == BITS9(1,1,1,1,1,0,1,1,0)
18831       && INSN0(6,4) == BITS3(1,0,1)
18832       && INSN1(7,5) == BITS3(0,0,0)) {
18833      UInt bitR = INSN1(4,4);
18834      UInt rA = INSN1(15,12);
18835      UInt rD = INSN1(11,8);
18836      UInt rM = INSN1(3,0);
18837      UInt rN = INSN0(3,0);
18838      if (!isBadRegT(rD) && !isBadRegT(rN) && !isBadRegT(rM) && (rA != 13)) {
18839         IRExpr* res
18840         = unop(Iop_64HIto32,
18841                binop(Iop_Add64,
18842                      binop(Iop_Add64,
18843                            binop(Iop_32HLto64, getIRegT(rA), mkU32(0)),
18844                            binop(Iop_MullS32, getIRegT(rN), getIRegT(rM))),
18845                      mkU64(bitR ? 0x80000000ULL : 0ULL)));
18846         putIRegT(rD, res, condT);
18847         DIP("smmla%s r%u, r%u, r%u, r%u\n",
18848             bitR ? "r" : "", rD, rN, rM, rA);
18849         goto decode_success;
18850      }
18851   }
18852
18853   /* ----------------------------------------------------------- */
18854   /* -- VFP (CP 10, CP 11) instructions (in Thumb mode)       -- */
18855   /* ----------------------------------------------------------- */
18856
18857   if (INSN0(15,12) == BITS4(1,1,1,0)) {
18858      UInt insn28 = (INSN0(11,0) << 16) | INSN1(15,0);
18859      Bool ok_vfp = decode_CP10_CP11_instruction (
18860                       &dres, insn28, condT, ARMCondAL/*bogus*/,
18861                       True/*isT*/
18862                    );
18863      if (ok_vfp)
18864         goto decode_success;
18865   }
18866
18867   /* ----------------------------------------------------------- */
18868   /* -- NEON instructions (in Thumb mode)                     -- */
18869   /* ----------------------------------------------------------- */
18870
18871   if (archinfo->hwcaps & VEX_HWCAPS_ARM_NEON) {
18872      UInt insn32 = (INSN0(15,0) << 16) | INSN1(15,0);
18873      Bool ok_neon = decode_NEON_instruction(
18874                        &dres, insn32, condT, True/*isT*/
18875                     );
18876      if (ok_neon)
18877         goto decode_success;
18878   }
18879
18880   /* ----------------------------------------------------------- */
18881   /* -- v6 media instructions (in Thumb mode)                 -- */
18882   /* ----------------------------------------------------------- */
18883
18884   { UInt insn32 = (INSN0(15,0) << 16) | INSN1(15,0);
18885     Bool ok_v6m = decode_V6MEDIA_instruction(
18886                      &dres, insn32, condT, ARMCondAL/*bogus*/,
18887                      True/*isT*/
18888                   );
18889     if (ok_v6m)
18890        goto decode_success;
18891   }
18892
18893   /* ----------------------------------------------------------- */
18894   /* -- Undecodable                                           -- */
18895   /* ----------------------------------------------------------- */
18896
18897   goto decode_failure;
18898   /*NOTREACHED*/
18899
18900  decode_failure:
18901   /* All decode failures end up here. */
18902   vex_printf("disInstr(thumb): unhandled instruction: "
18903              "0x%04x 0x%04x\n", (UInt)insn0, (UInt)insn1);
18904
18905   /* Back up ITSTATE to the initial value for this instruction.
18906      If we don't do that, any subsequent restart of the instruction
18907      will restart with the wrong value. */
18908   if (old_itstate != IRTemp_INVALID)
18909      put_ITSTATE(old_itstate);
18910
18911   /* Tell the dispatcher that this insn cannot be decoded, and so has
18912      not been executed, and (is currently) the next to be executed.
18913      R15 should be up-to-date since it made so at the start of each
18914      insn, but nevertheless be paranoid and update it again right
18915      now. */
18916   vassert(0 == (guest_R15_curr_instr_notENC & 1));
18917   llPutIReg( 15, mkU32(guest_R15_curr_instr_notENC | 1) );
18918   dres.whatNext    = Dis_StopHere;
18919   dres.jk_StopHere = Ijk_NoDecode;
18920   dres.len         = 0;
18921   return dres;
18922
18923  decode_success:
18924   /* All decode successes end up here. */
18925   vassert(dres.len == 4 || dres.len == 2 || dres.len == 20);
18926   switch (dres.whatNext) {
18927      case Dis_Continue:
18928         llPutIReg(15, mkU32(dres.len + (guest_R15_curr_instr_notENC | 1)));
18929         break;
18930      case Dis_ResteerU:
18931      case Dis_ResteerC:
18932         llPutIReg(15, mkU32(dres.continueAt));
18933         break;
18934      case Dis_StopHere:
18935         break;
18936      default:
18937         vassert(0);
18938   }
18939
18940   DIP("\n");
18941
18942   return dres;
18943
18944#  undef INSN0
18945#  undef INSN1
18946}
18947
18948#undef DIP
18949#undef DIS
18950
18951
18952/* Helper table for figuring out how many insns an IT insn
18953   conditionalises.
18954
18955   An ITxyz instruction of the format "1011 1111 firstcond mask"
18956   conditionalises some number of instructions, as indicated by the
18957   following table.  A value of zero indicates the instruction is
18958   invalid in some way.
18959
18960   mask = 0 means this isn't an IT instruction
18961   fc = 15 (NV) means unpredictable
18962
18963   The line fc = 14 (AL) is different from the others; there are
18964   additional constraints in this case.
18965
18966          mask(0 ..                   15)
18967        +--------------------------------
18968   fc(0 | 0 4 3 4 2 4 3 4 1 4 3 4 2 4 3 4
18969   ..   | 0 4 3 4 2 4 3 4 1 4 3 4 2 4 3 4
18970        | 0 4 3 4 2 4 3 4 1 4 3 4 2 4 3 4
18971        | 0 4 3 4 2 4 3 4 1 4 3 4 2 4 3 4
18972        | 0 4 3 4 2 4 3 4 1 4 3 4 2 4 3 4
18973        | 0 4 3 4 2 4 3 4 1 4 3 4 2 4 3 4
18974        | 0 4 3 4 2 4 3 4 1 4 3 4 2 4 3 4
18975        | 0 4 3 4 2 4 3 4 1 4 3 4 2 4 3 4
18976        | 0 4 3 4 2 4 3 4 1 4 3 4 2 4 3 4
18977        | 0 4 3 4 2 4 3 4 1 4 3 4 2 4 3 4
18978        | 0 4 3 4 2 4 3 4 1 4 3 4 2 4 3 4
18979        | 0 4 3 4 2 4 3 4 1 4 3 4 2 4 3 4
18980        | 0 4 3 4 2 4 3 4 1 4 3 4 2 4 3 4
18981        | 0 4 3 4 2 4 3 4 1 4 3 4 2 4 3 4
18982        | 0 4 3 0 2 0 0 0 1 0 0 0 0 0 0 0
18983   15)  | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
18984
18985   To be conservative with the analysis, let's rule out the mask = 0
18986   case, since that isn't an IT insn at all.  But for all the other
18987   cases where the table contains zero, that means unpredictable, so
18988   let's say 4 to be conservative.  Hence we have a safe value for any
18989   IT (mask,fc) pair that the CPU would actually identify as an IT
18990   instruction.  The final table is
18991
18992          mask(0 ..                   15)
18993        +--------------------------------
18994   fc(0 | 0 4 3 4 2 4 3 4 1 4 3 4 2 4 3 4
18995   ..   | 0 4 3 4 2 4 3 4 1 4 3 4 2 4 3 4
18996        | 0 4 3 4 2 4 3 4 1 4 3 4 2 4 3 4
18997        | 0 4 3 4 2 4 3 4 1 4 3 4 2 4 3 4
18998        | 0 4 3 4 2 4 3 4 1 4 3 4 2 4 3 4
18999        | 0 4 3 4 2 4 3 4 1 4 3 4 2 4 3 4
19000        | 0 4 3 4 2 4 3 4 1 4 3 4 2 4 3 4
19001        | 0 4 3 4 2 4 3 4 1 4 3 4 2 4 3 4
19002        | 0 4 3 4 2 4 3 4 1 4 3 4 2 4 3 4
19003        | 0 4 3 4 2 4 3 4 1 4 3 4 2 4 3 4
19004        | 0 4 3 4 2 4 3 4 1 4 3 4 2 4 3 4
19005        | 0 4 3 4 2 4 3 4 1 4 3 4 2 4 3 4
19006        | 0 4 3 4 2 4 3 4 1 4 3 4 2 4 3 4
19007        | 0 4 3 4 2 4 3 4 1 4 3 4 2 4 3 4
19008        | 0 4 3 4 2 4 4 4 1 4 4 4 4 4 4 4
19009   15)  | 0 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4
19010*/
19011static const UChar it_length_table[256]
19012   = { 0, 4, 3, 4, 2, 4, 3, 4, 1, 4, 3, 4, 2, 4, 3, 4,
19013       0, 4, 3, 4, 2, 4, 3, 4, 1, 4, 3, 4, 2, 4, 3, 4,
19014       0, 4, 3, 4, 2, 4, 3, 4, 1, 4, 3, 4, 2, 4, 3, 4,
19015       0, 4, 3, 4, 2, 4, 3, 4, 1, 4, 3, 4, 2, 4, 3, 4,
19016       0, 4, 3, 4, 2, 4, 3, 4, 1, 4, 3, 4, 2, 4, 3, 4,
19017       0, 4, 3, 4, 2, 4, 3, 4, 1, 4, 3, 4, 2, 4, 3, 4,
19018       0, 4, 3, 4, 2, 4, 3, 4, 1, 4, 3, 4, 2, 4, 3, 4,
19019       0, 4, 3, 4, 2, 4, 3, 4, 1, 4, 3, 4, 2, 4, 3, 4,
19020       0, 4, 3, 4, 2, 4, 3, 4, 1, 4, 3, 4, 2, 4, 3, 4,
19021       0, 4, 3, 4, 2, 4, 3, 4, 1, 4, 3, 4, 2, 4, 3, 4,
19022       0, 4, 3, 4, 2, 4, 3, 4, 1, 4, 3, 4, 2, 4, 3, 4,
19023       0, 4, 3, 4, 2, 4, 3, 4, 1, 4, 3, 4, 2, 4, 3, 4,
19024       0, 4, 3, 4, 2, 4, 3, 4, 1, 4, 3, 4, 2, 4, 3, 4,
19025       0, 4, 3, 4, 2, 4, 3, 4, 1, 4, 3, 4, 2, 4, 3, 4,
19026       0, 4, 3, 4, 2, 4, 4, 4, 1, 4, 4, 4, 4, 4, 4, 4,
19027       0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4
19028     };
19029
19030
19031/*------------------------------------------------------------*/
19032/*--- Top-level fn                                         ---*/
19033/*------------------------------------------------------------*/
19034
19035/* Disassemble a single instruction into IR.  The instruction
19036   is located in host memory at &guest_code[delta]. */
19037
19038DisResult disInstr_ARM ( IRSB*        irsb_IN,
19039                         Bool         (*resteerOkFn) ( void*, Addr64 ),
19040                         Bool         resteerCisOk,
19041                         void*        callback_opaque,
19042                         UChar*       guest_code_IN,
19043                         Long         delta_ENCODED,
19044                         Addr64       guest_IP_ENCODED,
19045                         VexArch      guest_arch,
19046                         VexArchInfo* archinfo,
19047                         VexAbiInfo*  abiinfo,
19048                         Bool         host_bigendian_IN )
19049{
19050   DisResult dres;
19051   Bool isThumb = (Bool)(guest_IP_ENCODED & 1);
19052
19053   /* Set globals (see top of this file) */
19054   vassert(guest_arch == VexArchARM);
19055
19056   irsb              = irsb_IN;
19057   host_is_bigendian = host_bigendian_IN;
19058   __curr_is_Thumb   = isThumb;
19059
19060   if (isThumb) {
19061      guest_R15_curr_instr_notENC = (Addr32)guest_IP_ENCODED - 1;
19062   } else {
19063      guest_R15_curr_instr_notENC = (Addr32)guest_IP_ENCODED;
19064   }
19065
19066   if (isThumb) {
19067      dres = disInstr_THUMB_WRK ( resteerOkFn,
19068                                  resteerCisOk, callback_opaque,
19069                                  &guest_code_IN[delta_ENCODED - 1],
19070                                  archinfo, abiinfo );
19071   } else {
19072      dres = disInstr_ARM_WRK ( resteerOkFn,
19073                                resteerCisOk, callback_opaque,
19074                                &guest_code_IN[delta_ENCODED],
19075                                archinfo, abiinfo );
19076   }
19077
19078   return dres;
19079}
19080
19081/* Test program for the conversion of IRCmpF64Result values to VFP
19082   nzcv values.  See handling of FCMPD et al above. */
19083/*
19084UInt foo ( UInt x )
19085{
19086   UInt ix    = ((x >> 5) & 3) | (x & 1);
19087   UInt termL = (((((ix ^ 1) << 30) - 1) >> 29) + 1);
19088   UInt termR = (ix & (ix >> 1) & 1);
19089   return termL  -  termR;
19090}
19091
19092void try ( char* s, UInt ir, UInt req )
19093{
19094   UInt act = foo(ir);
19095   printf("%s 0x%02x -> req %d%d%d%d act %d%d%d%d (0x%x)\n",
19096          s, ir, (req >> 3) & 1, (req >> 2) & 1,
19097                 (req >> 1) & 1, (req >> 0) & 1,
19098                 (act >> 3) & 1, (act >> 2) & 1,
19099                 (act >> 1) & 1, (act >> 0) & 1, act);
19100
19101}
19102
19103int main ( void )
19104{
19105   printf("\n");
19106   try("UN", 0x45, 0b0011);
19107   try("LT", 0x01, 0b1000);
19108   try("GT", 0x00, 0b0010);
19109   try("EQ", 0x40, 0b0110);
19110   printf("\n");
19111   return 0;
19112}
19113*/
19114
19115/*--------------------------------------------------------------------*/
19116/*--- end                                         guest_arm_toIR.c ---*/
19117/*--------------------------------------------------------------------*/
19118